Не удается скомпилировать коррелированные параметры Java Generics с подстановочными знаками

Следующий небольшой пример Java не будет компилироваться по непонятным причинам:

package genericsissue;

import java.util.ArrayList;
import java.util.List;

interface Attribute<V> {}

interface ListAttribute extends Attribute<List<?>> {}

public class Context {
    public <T, A extends Attribute<T>> void put(Class<A> attribute, T value) {
        // implementation does not matter for the issue
    }

    public static void main(String[] args) {
        Context ctx = new Context();
        List<?> list = new ArrayList<String>();
        ctx.put(ListAttribute.class, list);
    }
}

Строка с ctx.put выдает следующую ошибку:

Context.java:18: <T,A>put(java.lang.Class<A>,T) in genericsissue.Context cannot be applied to (java.lang.Class<genericsissue.ListAttribute>,java.util.List<capture#35 of ?>)

При работе без подстановочных знаков шаблон атрибута работает нормально.

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

2 ответа

Решение

Замещать

public <T, A extends Attribute<T>>

С

public <T, A extends Attribute<? super T>>

Проблема в том, что тип аргумента list не совсем List<?>, Компилятор сначала делает "захват", чтобы преобразовать его тип в List<x> for some x, Обычно это более информативно и полезно. Но не в вашем случае. Это заставляет думать, что T=List<x>, но ListAttribute не распространяется Attribute<List<x>>

Вы можете предоставить явные аргументы типа, чтобы обойти это

ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
      (T)      (A)
Другие вопросы по тегам