Создание универсального класса типа <?>
Я учусь на SCJP/OCPJP, и я наткнулся на пример вопроса, который кажется мне странным.
В примере кода созданы две общие коллекции:
List<?> list = new ArrayList<?>();
List<? extends Object> list2 = new ArrayList<? extends Object>();
"Правильный" ответ на вопрос состоял в том, что этот код будет компилироваться, но добавление в любую коллекцию приведет к ошибке времени выполнения.
Когда я пытаюсь скомпилировать такой код, я просто получаю ошибки. Учебник Java даже не показывает этот тип кода, вместо этого он обычно использует подстановочные знаки как часть upcast.
Collection<?> c = new ArrayList<String>();
Являются ли две общие коллекции выше даже законным кодом? Второй по моей логике будет только запрещать интерфейсы. Первый выглядит совершенно бесполезным. Зачем использовать универсальный, который не пытается контролировать?
4 ответа
Ознакомьтесь с отличным учебным пособием по дженерикам Java в формате PDF В частности, раздел о подстановочных знаках содержит ответ на ваш вопрос, и я цитирую
Collection<?> c = new ArrayList<String>();
c.add( new Object() );
Поскольку мы не знаем, какой тип элемента
c
означает, что мы не можем добавлять объекты к нему.add()
метод принимает аргументы типаE
тип элемента коллекции. Когда фактический параметр типа?
, это обозначает некоторый неизвестный тип. Любой параметр, который мы передаем для добавления, должен быть подтипом этого неизвестного типа. Так как мы не знаем, что это за тип, мы не можем ничего передать. Единственное исключениеnull
, который является членом каждого типа.
Если вы хотите объявить Type во время выполнения, вы можете сделать что-то вроде этого:
public class Clazz1<T> {
private final List<T> list = new ArrayList<T>();
private List<T> getList() {
return list;
}
/**
* @param args
*/
public static void main(String[] args) {
Clazz1<Integer> clazzInt = new Clazz1<Integer>();
clazzInt.getList().add(2);
System.out.println(clazzInt.getList());
Clazz1<String> clazzString = new Clazz1<String>();
clazzString.getList().add("test");
System.out.println(clazzString.getList());
}
}
Я ответил на это несколько раньше в этом ответе. ?
не может быть использован в создании экземпляра. Я не уверен, почему написано, что код будет компилироваться, ни один из используемых мной компиляторов Java не позволил бы этого. Вы можете сделать то, что показано выше следующим образом:
List<?> list = new ArrayList();
Это скомпилирует и запустит, но вы не можете сделать:
list.add("hello world"); //This wouldn't compile
new
производит конкретный экземпляр объекта. Конкретный экземпляр может иметь только один тип, включая любые универсальные. Зная это, шаблоны не могут работать с new
,