Здесь есть две проблемы.
(a) new ArrayList<?>
не является допустимым выражением.
Если вы хотите создать список, который может содержать строки и целые числа, вам нужно использовать ArrayList<Object>
, поскольку Object
является (наиболее конкретным) распространенным супертипом String
и Integer
:
ArrayList<Object> list = new ArrayList<Object>;
list.add('abcd'); // insert a string
list.add(1234); // insert an integer
Недостатком является то, что когда вы извлекаете элемент из этого списка, он будет иметь тип Object
, поэтому вам нужно будет его преобразовать:
String s = (String) list.get(0);
Integer n = (Integet) list.get(1);
(b) Что касается подстановочного знака ?
:
Его можно использовать для указания типа переменной, например: ArrayList<?> list = ...
, но его нельзя использовать в выражении new
. Другими словами, это выражение недопустимо: new ArrayList<?>
.
Подстановочный знак полезен для разрешения (ограниченного) полиморфизма между списками. В частности, если у вас есть список Integer
и вы хотите рассматривать его как список Number
(что имеет смысл, поскольку Integer
является подклассом Number
), вы можете использовать подстановочный знак.
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(100);
list2.add(200);
// This assignment is OK:
ArrayList<? extends Number> list3 = list2;
Number n = list3.get(0); // n is now 100
Однако проблема со списком3 (или любым другим списком с подстановочным знаком) заключается в том, что вы не можете изменить его. Например, если вы попытаетесь добавить элемент в этот список:
list3.add(300); // <-- This is not allowed
вы получите ошибку времени компиляции.
person
Itay Maman
schedule
05.07.2014
List<?>
как интерфейс в значительной степени соответствует границамList<? extends Object>
. На самом деле не сильно ограничивает. - person EpicPandaForce   schedule 05.07.2014