Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incompatible generic type in Java

Tags:

java

generics

I have a complex generic type implementation in Java but I could not complete it. I am getting error on AddItemEvent class. The return type in the getHandler does not match with it's parent class requires.

AddItemEventHandler is actually a BaseEventHandler<BaseEvent<AddItemCommand, AddItemPayload>, AddItemCommand, AddItemPayload> but I get an error on that line.


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>'
        */
    }
}









like image 772
feyzullahyildiz Avatar asked Aug 30 '26 18:08

feyzullahyildiz


1 Answers

You cannot assign a variable of type List<AddItemEvent> to a reference of type List<BaseEvent<AddItemCommand, AddItemPayload>>. That's because the latter allows more - it allows not just AddItemEvent instances, but any instance that extends BaseEvent<AddItemCommand, AddItemPayload>.

Your compiler error has the same cause. The handler would allow more than only AddItemEvent instances.

One solution can be to add an extra generic type to BaseEvent for the event itself:

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

That has to be propagated to some of the other types:

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
    }
}
like image 148
Rob Spoor Avatar answered Sep 01 '26 08:09

Rob Spoor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!