Использование универсального интерфейса внутри другого универсального интерфейса

1

У меня есть переменная e4 типа List<List<Integer>>, которую я бы хотел инициализировать new ArrayList<ArrayList<Integer>>(). Я ожидаю, что это сработает, подобно тому, как можно назначить переменной List<Integer> -type new ArrayList<Integer>(). Вместо этого возникает ошибка компиляции; какова причина этого, и нужно ли тогда использовать такое утверждение, как e3 или e5?

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

public class Example {
    public static void main(String[] args) {
        // e1-3 compile as expected
        ArrayList<Integer> e1 = new ArrayList<Integer>();
        List<Integer> e2 = new ArrayList<Integer>();
        ArrayList<ArrayList<Integer>> e3 = new ArrayList<ArrayList<Integer>>();
        // e4 does not compile
        List<List<Integer>> e4 = new ArrayList<ArrayList<Integer>>();
        // e5 does compile
        List<ArrayList<Integer>> e5 = new ArrayList<ArrayList<Integer>>();
    }
}

При попытке скомпилировать выше, я получаю сообщение об ошибке:

/home/james/Example.java:12: error: incompatible types
        List<List<Integer>>           e4 = new ArrayList<ArrayList<Integer>>();
                                           ^
required: List<List<Integer>>
found:    ArrayList<ArrayList<Integer>>
1 error
Теги:
generics
interface
nested

4 ответа

4
Лучший ответ

Причина в том, что List<ArrayList<Integer>> не является List<List<Integer>>, хотя ArrayList<Integer> является List<Integer>. Обоснование здесь аналогично тому, что List<Dog> не является List<Animal>, хотя Dog является Animal. Аналогия заключается в том, что ArrayList<Integer> означает List<Integer> поскольку Dog для Animal.

Ниже приведены альтернативы:

1) Ваш "e5", который точно соответствует типичному типу.

List<ArrayList<Integer>>      e5 = new ArrayList<ArrayList<Integer>>();

или

List<List<Integer>> e5 = new ArrayList<List<Integer>>();

2) Использование подстановочного знака:

List<? extends List<Integer>>      e6 = new ArrayList<ArrayList<Integer>>();
0
Whenever you are specifying ;

List<List<Integer>> e4 = new ArrayList<ArrayList<Intger>>();

This stands out to be wrong because when you are creating the ArrayList (Implementation of the List) e4 you are specifying that it can contain List (all kinds of implementation of lists) of Integer but while instantiating it you are strictly specifying it as ArrayList of Integer which is contradicting with your declaration.

Moreover Polymorphism only applies to the base type (Base type means the collection class itself.)

Your example can be correlated with another example : 

List<Number> l1= new ArrayList<Integer>(); /*This will never compile though Integer is a subclass of Number as we are not only changing the base type but also the generic type which is wrong.*/

But this will definitely compile 

List<Number> l2 =new ArrayList<Number>(); //Changed only the base type.


For better understanding read Sun Certified Programmer for Java 6 by Kathy Sierra and Bert Bates.
0

Как работает java

List<List<Integer>> list = new ArrayList<ArrayList<Integer>>

не будет работать, потому что внутренний ArrayList не соответствует типу List. Он ищет именно список.

Вы хотите следующее

List<? extends List<Integer>> list = new ArrayList<ArrayList<Integer>>();
0

Причина в том, что дженерики в Java инвариантны. Сначала рассмотрим очень простой пример:

// This doesn't compile
List<Number> list = new ArrayList<Integer>();

Вышеприведенное назначение не будет компилироваться, потому что ArrayList<Integer> не является подтипом List<Number>, хотя Integer является подтипом Number.

Используя эту концепцию для вложенных дженериков:

// This also shouldn't compile
List<List<Integer>> list = new ArrayList<ArrayList<Integer>>();

Хотя ArrayList<Integer> является подтипом List<Integer>, это не делает ArrayList<ArrayList<Integer>> подтипом List<List<Integer>>. Поэтому он не компилируется.

Чтобы скомпилировать его, вы можете использовать ограниченные подстановочные знаки:

// This would work now.
List<? extends List<Integer>> list = new ArrayList<ArrayList<Integer>>();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню