Общие типы: подстановочные знаки против переменных необработанных типов
Рассмотрим следующие методы:
public static void listAll(LinkedList list) {
for(Object obj : list)
System.out.println(obj);
}
а также
public static void listAll(LinkedList<?> list) {
for(Object obj : list)
System.out.println(obj);
}
В чем разница между этими двумя методами? Если нет разницы, почему мы должны использовать второй?
2 ответа
<?>
не позволяет добавлять объекты в список. Смотрите программу ниже. Это конкретный тип списка, который мы передали методу <?>
,
Определенные средства, список был создан с определенным типом и передан <?>
метод listAll
, Не путай со словом specific
,
Специфическим может быть любой нормальный объект, например, Dog, Tiger, String, Object, HashMap, File, Integer, Long.... и список бесконечен. JLS
сил <?>
метод не выполнять добавить любой irrelevant objects
в называется <?>
метод, который вы определили (определено в вызывающем методе, а не в called-listAll
) список, содержащий specific type
объекта.
Это как <?>
говоря "не трогай меня".
public static void listAll(LinkedList list)
{
list.add(new String()); //works fine
for(Object obj : list)
System.out.println(obj);
}
public static void listAll(LinkedList<?> list)
{
list.add(new String()); //compile time error. Only 'null' is allowed.
for(Object obj : list)
System.out.println(obj);
}
Теперь давайте посмотрим на другой сценарий. Что произойдет, когда мы объявим определенный тип, например, Dog, Tiger, Object, String ... что угодно. Давайте изменим метод на specific type
,
public static void listAll(LinkedList<String> list)// It is now specific type, 'String'
{
list.add(new String());//works fine. Compile time it knows that 'list' has 'String'
for(Object obj : list)
System.out.println(obj);
}
List
это сырой тип, List<?>
является универсальным типом с подстановочным аргументом.
Предположим, что у нас есть следующие переменные:
List<?> a;
List<String> b;
List c;
Назначение b=a
дает ошибку времени компиляции (List<String>
не присваивается List<?
), но c=a
компилирует нормально (List<String>
присваивается необработанному типу List
для совместимости с устаревшим кодом, не использующим дженерики).
Назначение b=c
выдает предупреждение во время компиляции (List<?>
не присваивается List<String>
), но a=c
компилирует нормально (List<String>
присваивается List<?>
)