Java Generic, относящийся к базовому и дочернему классам, не применим для аргументов

Я нашел похожие сообщения по общим проблемам, но ни один из них не охватил мою проблему так, как я мог ее понять. Я надеюсь, что кто-то может помочь мне с этим случаем.

Я пробовал много вещей, таких как удаление «? extends» из разных мест и игра с «? super», чтобы увидеть, не укажет ли мне другая ошибка в направлении решения.

Следующий код:

final ResponseBase response = executor.execute(myRequest);

Выдает следующую ошибку компилятора: "Метод execute(capture#6-of? extends RequestBase) в типе CommandExecutor неприменим для аргументов (RequestBase)"

Полный листинг кода:

public class MainClass {

    private final static Map<Class<? extends RequestBase>, CommandExecutor<? extends RequestBase, ? extends ResponseBase>> MAP = new HashMap<>();

    public static void main(String[] args) {

        final DummyCommandExecutor dummyCommandExecutor = new DummyCommandExecutor();
        MAP.put(MyRequest.class, dummyCommandExecutor);

        final RequestBase myRequest = new MyRequest();
        myRequest.setRequestString("this is my request");

        final CommandExecutor<? extends RequestBase, ? extends ResponseBase> executor = MAP.get(myRequest.getClass());

        final ResponseBase response = executor.execute(myRequest);

        System.out.println(response.getResponseString());
    }
}

interface CommandExecutor<T, R> {

    R execute(T object);

}

class DummyCommandExecutor implements CommandExecutor<MyRequest, MyResponse> {

    @Override
    public MyResponse execute(MyRequest request) {

        final MyResponse response = new MyResponse();
        response.setResponseString(request.getRequestString());

        return response;
    }

}

class MyResponse extends ResponseBase {

}

class ResponseBase {
    String responseString;

    public String getResponseString() {
        return this.responseString;
    }

    public void setResponseString(String responseString) {
        this.responseString = responseString;
    }
}

class MyRequest extends RequestBase {

}

class RequestBase {
    String requestString;

    public String getRequestString() {
        return this.requestString;
    }

    public void setRequestString(String requestString) {
        this.requestString = requestString;
    }

}

person HaTo    schedule 31.03.2016    source источник


Ответы (2)


Вы не можете сделать это без кастинга. Хотя вы знаете, что карта вернет правильный исполнитель команды для данного типа, компилятор этого не знает, поэтому вам нужно сообщить компилятору, что ему все равно:

final CommandExecutor<RequestBase,ResponseBase> executor = (CommandExecutor) MAP.get(myRequest.getClass());
person Darth Android    schedule 31.03.2016
comment
Спасибо, это помогло! Все еще не уверен, почему компилятор не знает. Компилятор должен знать, что HashMap содержит значение CommandExecutor‹? расширяет RequestBase, ? расширяет базу ответов› - person HaTo; 01.04.2016
comment
Проблема в том, что ? может быть любым классом, расширяющим RequestBase. Компилятор не знает, что ? extends RequestBase в ключе карты всегда совпадает с ? extends RequestBase в возвращаемом CommandExecutor. - person Darth Android; 01.04.2016

вы не можете просто соответствовать? с Т

вариант просто сделать:

final CommandExecutor executor = MAP.get(myRequest.getClass());

в каком варианте, конечно, вы можете получить исключение времени выполнения, если карта возвращает что-то не приводимое

person kalin    schedule 31.03.2016