Подтвердить что ты не робот

Несоответствие типичного типа Java

В следующем примере:

public static void main(String[] args) {

    List<String> b = new ArrayList<String>();
    first(b);
    second(b);

    List<List<String>> a = new ArrayList<List<String>>();
    third(a);
    fourth(a);  // doesnt work

}

private static <T> void first(List<T> a){
    System.out.println("List of T");
}

private static void second(List<?> a){
    System.out.println("List of anything ");
}

private static <T> void third(List<List<T>> a){
    System.out.println("List of a List of T ");
}

private static void fourth(List<List<?>> a){
    System.out.println("List of a List of anything ");
}

Почему вызов второго (б) работает, но вызов четвертого (а) не?

Я получаю следующую ошибку:

The method fourth(List<List<?>>) in the type `TestTest` is not applicable for the arguments (`List<List<String>>`)
4b9b3361

Ответ 1

Если вы хотите иметь возможность вызывать fourth с аргументом List<List<String>>, вам нужно будет изменить свою подпись на это:

private static void fourth(List<? extends List<?>> a){
    System.out.println("List of a List of anything ");
}

Вышеупомянутое будет работать, потому что в отличие от List<List<?>>, List<? extends List<?>> совместимо с List<List<String>>. Подумайте об этом так:

List<List<String>> original = null;
List<? extends List<?>> ok  = original; // This works
List<?> ok2                 = original; // So does this
List<List<?>> notOk         = original; // This doesn't

List<Integer> original      = null;
List<? extends Number> ok   = original; // This works
List<?> ok2                 = original; // So does this
List<Number> notOk          = original; // This doesn't

Простые рассуждения. Если у вас

private static void fourth(List<List<?>> a) {
    List<?> ohOh = Arrays.asList(new Object());
    a.add(ohOh);
}

И тогда, если вы могли бы вызвать этот метод как таковой:

List<List<String>> a = new ArrayList<List<String>>();
fourth(a);
String fail = a.get(0).get(0); // ClassCastException here!

Ответ 2

A List<List<String>> не является List<List<?>>.

Вы можете поместить любой List<?> в List<List<?>>, независимо от того, что ?. A List<List<String>> принимает только List<String>.

Ответ 3

Это означает, что тип неизвестен, а объекты любого типа могут быть добавлены в List<List<?>>, которые являются heterogeneous, а компилятор не может гарантировать, что все объекты в List<List<?>> имеют одинаковый тип. Следовательно, он не может быть передан новому ArrayList<List<String>>(), который принимает ограниченный тип в качестве параметра.

Ответ 4

List<List<String>> не совпадает с List<List<?>>. Дженерики носят инвариантный характер. Если вы выполняете только List<?> и проходите List<String>, тогда он будет работать, потому что List of Anything может быть представлен Lists of String.

Но List of List of anything не может быть представлено List of List of String.

@Lukas Elder уже указал случай, который будет работать. Вот второй случай, который будет работать

private static void fourth(List<?> a){
    System.out.println("List of anything ");
}

Ответ 5

List<List<?>> == List {                 //That contains any unknown type lists
                        List<Integer>,
                        List<String>,
                        List<Object>
                      }

Где

List<? extends List<?> == List {       //That contains same unknown type lists
                        List<Integer>,
                        List<Integer>,
                        List<Integer>
                      }

Итак, здесь

 List<List<String>> == List {        //That contains same String lists
                        List<String>,
                        List<String>,
                        List<String>
                      }

Следовательно, List<? extends List<?> является супер-типом List<List<String>> и присваивается.

Допустимое значение для вызова метода fourth приведено ниже.

    List<List<?>> a1 =  new ArrayList<List<?>>();
    a1.add(new ArrayList<String>());
    a1.add(new ArrayList<Integer>());
    a1.add(new ArrayList<Object>());