Создание универсального класса типа <?> - PullRequest
2 голосов
/ 30 декабря 2011

Я учусь на SCJP / OCPJP и натолкнулся на пример вопроса, который кажется мне странным.

В примере кода созданы две общие коллекции:

List<?> list = new ArrayList<?>();
List<? extends Object> list2 = new ArrayList<? extends Object>();

"Правильный ответ на вопрос состоял в том, что этот код будет компилироваться, но добавление в любую коллекцию приведет к ошибке времени выполнения.

Когда я пытаюсь скомпилировать код, я просто получаю ошибки.Учебник по Java даже не показывает этот тип кода, вместо этого он обычно использует подстановочные знаки как часть апскейтинга.

Collection<?> c = new ArrayList<String>();

Являются ли две общие коллекции выше даже допустимым кодом?Второй по моей логике будет только запрещать интерфейсы.Первый выглядит совершенно бесполезным.Зачем использовать универсальный, который не пытается контролировать?

Ответы [ 4 ]

4 голосов
/ 30 декабря 2011

Ознакомьтесь с превосходным учебным пособием по языку Java PDF .В частности, раздел о подстановочных знаках содержит ответ на ваш вопрос, и я цитирую

Collection<?> c = new ArrayList<String>();
c.add( new Object() );

Поскольку мы не знаем, что означает тип элемента c, мы не можем добавлять объекты вЭто.Метод add() принимает аргументы типа E, типа элемента коллекции.Когда фактический параметр типа равен ?, он обозначает некоторый неизвестный тип.Любой параметр, который мы передаем для добавления, должен быть подтипом этого неизвестного типа.Поскольку мы не знаем, что это за тип, мы не можем ничего передать. Единственное исключение - null, который является членом каждого типа.

2 голосов
/ 30 декабря 2011

Если вы хотите объявить 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());
}

}
1 голос
/ 30 декабря 2011

Я уже несколько раз отвечал на это в этом ответе. ? нельзя использовать в инстанции. Я не уверен, почему написано, что код будет компилироваться, ни один из используемых мной компиляторов Java не позволил бы этого. Вы можете сделать то, что показано выше следующим образом:

List<?> list = new ArrayList();

Это скомпилирует и запустит, но вы не сможете:

list.add("hello world"); //This wouldn't compile
0 голосов
/ 31 декабря 2011

new создает конкретный экземпляр объекта.Конкретный экземпляр может иметь только один тип, включая любые обобщения.Зная это, подстановочные знаки не могут работать с new.

...