Несвязанный тип может быть полезен, когда ваш метод на самом деле не заботится о реальном типе.
Примитивный пример будет таким:
public void printStuff(Iterable<?> stuff) {
for (Object item : stuff) {
System.out.println(item);
}
}
Поскольку PrintStream.println()
может обрабатывать все ссылочные типы (вызывая toString()
), мы не заботимся , каково фактическое содержание этого Iterable
.
И абонент может передать List<Number>
или Set<String>
или Collection<? extends MySpecificObject<SomeType>>
.
Также обратите внимание, что отсутствие использования обобщений (которое вызывается с использованием необработанного типа) вообще имеет совершенно иной эффект: он заставляет компилятор обрабатывать весь объект , как если бы обобщения не существовали на все . Другими словами: игнорируется не только параметр типа класса, но и все параметры универсального типа в методах.
Другим важным отличием является то, что вы не можете добавить любое (не null
) значение к Collection<?>
, но можете добавить все объекты к необработанному типу Collection
:
Это не скомпилируется, поскольку параметр типа c
является неизвестным типом (= подстановочный знак ?
), поэтому мы не можем предоставить значение, которое гарантированно будет назначено этому (кроме *) 1035 *, который присваивается всем ссылочным типам).
Collection<?> c = new ArrayList<String>();
c.add("foo"); // compilation error
Если вы не укажете параметр типа (то есть используете необработанный тип), тогда вы можете добавить что угодно в коллекцию:
Collection c = new ArrayList<String>();
c.add("foo");
c.add(new Integer(300));
c.add(new Object());
Обратите внимание, что компилятор предупредит , что вам не следует использовать необработанный тип, особенно по этой причине: он удаляет любые проверки типов, связанные с обобщениями.