我在Java中有一个复杂的泛型类型实现,但我无法完成它.我在AddItemEvent节课上遇到了错误.getHandler中的返回类型与其父类要求的类型不匹配.

AddItemEventHandler实际上是BaseEventHandler<BaseEvent<AddItemCommand, AddItemPayload>, AddItemCommand, AddItemPayload>,但我在这条线上得到了一个错误.


public abstract class BasePayload {
}

public class AddItemPayload extends BasePayload {
    private int id;
    private String name;
    public AddItemPayload(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
}

public class BaseCommand<T extends BasePayload> {
    String command;
    T payload;

    public BaseCommand(String command, T payload) {
        this.command = command;
        this.payload = payload;
    }
}

public class AddItemCommand extends BaseCommand<AddItemPayload> {
    public AddItemCommand(AddItemPayload payload) {
        super("AddItem", payload);
    }
}


public abstract class BaseEventHandler<E extends BaseEvent<C, P>, C extends BaseCommand<P>, P extends BasePayload> {
    abstract public void onTry(E event, ArrayList<BaseEvent<?, ?>> actualEvents);
    abstract public void onCommit(String uuid, E event);
}

public class AddItemEventHandler extends BaseEventHandler<AddItemEvent, AddItemCommand, AddItemPayload> {
    @Override
    public void onTry(AddItemEvent event, ArrayList<BaseEvent<?, ?>> actualEvents) {
    }
    @Override
    public void onCommit(String uuid, AddItemEvent event) {
    }
}


public abstract class BaseEvent<C extends BaseCommand<P>, P extends BasePayload> {
    abstract protected BaseEventHandler<BaseEvent<C, P>, C, P> getHandler();
}

public class AddItemEvent extends BaseEvent<AddItemCommand, AddItemPayload> {
    @Override
    protected BaseEventHandler<BaseEvent<AddItemCommand, AddItemPayload>, AddItemCommand, AddItemPayload> getHandler() {
        return new AddItemEventHandler(); // I have an error on this line
        /*
        Incompatible types. Found: 'org.example.handlers.AddItemEventHandler',
        required: 'org.example.handlers.BaseEventHandler<org.example.events.BaseEvent<org.example.commands.AddItemCommand,org.example.payload.AddItemPayload>,
        org.example.commands.AddItemCommand,org.example.payload.AddItemPayload>'
        */
    }
}









推荐答案

不能将类型为List<AddItemEvent>的变量赋给类型为List<BaseEvent<AddItemCommand, AddItemPayload>>的引用.这是因为后者允许更多--它不仅允许AddItemEvent个实例,还允许扩展BaseEvent<AddItemCommand, AddItemPayload>个实例的任何实例.

你的编译器错误也有同样的原因.处理程序将允许超过AddItemEvent个实例.

一种解决方案是为事件本身添加一个额外的泛型类型到BaseEvent:

public abstract class BaseEvent<E extends BaseEvent<E, C, P>, C extends BaseCommand<P>, P extends BasePayload> {
    abstract protected BaseEventHandler<E, C, P> getHandler();
}

它必须传播到其他一些类型:

public abstract class BaseEventHandler<E extends BaseEvent<E, C, P>, C extends BaseCommand<P>, P extends BasePayload> {
    // additional ? in BaseEvent
    abstract public void onTry(E event, ArrayList<BaseEvent<?, ?, ?>> actualEvents);
    abstract public void onCommit(String uuid, E event);
}

public class AddItemEventHandler extends BaseEventHandler<AddItemEvent, AddItemCommand, AddItemPayload> {
    @Override
    // additional ? in BaseEvent
    public void onTry(AddItemEvent event, ArrayList<BaseEvent<?, ?, ?>> actualEvents) {
    }
    @Override
    public void onCommit(String uuid, AddItemEvent event) {
    }
}

// additional generic type: AddItemEvent
public class AddItemEvent extends BaseEvent<AddItemEvent, AddItemCommand, AddItemPayload> {
    @Override
    // replace BaseEvent<AddItemCommand, AddItemPayload> with AddItemEvent
    protected BaseEventHandler<AddItemEvent, AddItemCommand, AddItemPayload> getHandler() {
        return new AddItemEventHandler(); // no more error
    }
}

Java相关问答推荐

强制Mockito返回null而不是emtpy list

使用@MappdSuperClass扩展ParentClass&Won t继承ParentClass属性

流迭代列表<;对象>;上的NoSuchElementException

Jolt变换JSON数组问题

使SLF4J在Android中登录到Logcat,在测试中登录到控制台(Gradle依赖问题)

Tinylog中的滚动文件会在每次应用启动时覆盖日志(log)文件

在Java 15应用程序中运行Java脚本和Python代码

是否在settings.xml中使用条件Maven镜像?

我如何为我的Java抵押贷款代码执行加薪操作(&Q)

无法使用Java PreparedStatement在SQLite中的日期之间获取结果

具有最大共同前景像素的图像平移优化算法

我的代码是线程安全的吗?[Java、CAS、转账]

为什么相同的数据条码在视觉上看起来不同?

使用MediaPlayer类在一段时间后停止播放音乐

如何在Struts2中使用操作类中的结果注释重定向到不同的命名空间

为什么Spring要更改Java版本配置以及如何正确设置?

Java中的一个错误';s stdlib SocksSocketImpl?

如果c不为null,Arrays.sort(T[]a,Comparator<;?super T>;c)是否会引发ClassCastException?

Java泛型方法重载

原始和参数化之间的差异调用orElseGet时可选(供应商)