Почему ArrayList <ArrayList <? >> list = new ArrayList <ArrayList <String>>() не компилируется?
Почему этот код компилируется
final ArrayList<?> dp1 = new ArrayList<String>();
Но это не
final ArrayList<ArrayList<?>> dp2 = new ArrayList<ArrayList<String>>();
Ответ 1
В
final ArrayList<?> dp1 = new ArrayList<String>();
Аргумент типа ? является подстановочным знаком, который является надмножеством (не супер-типом) String. Итак, ArrayList<?> является супер-типом ArrayList<String>.
Но в
final ArrayList<ArrayList<?>> dp2 = new ArrayList<ArrayList<String>>();
Аргумент типа ArrayList<?> (параметризованный тип, где ? просто обозначает некоторый тип unkown и не имеет ничего общего с String), не является подстановочным знаком, подстановочный знак будет ? extends ArrayList<?>, с верхней границей ArrayList<?>, которая на самом деле является супертипом ArrayList<String>.
Вы можете прочитать о правилах относительно супер /sub set/type в параметризованном типе здесь.
Ответ 2
Это довольно сложно понять, но в итоге в вашем первом коде String extends ?, но второй не компилируется, потому что ArrayList<String> не наследует напрямую от ArrayList<?>, вы можете посмотреть здесь, если вы хотите получить все детали.
Если вы хотите, чтобы ваш второй пример был скомпилирован, вам необходимо изменить его на это:
final ArrayList<? extends ArrayList<?>> dp2 = new ArrayList<ArrayList<String>>();