Общие типы: подстановочные знаки против переменных необработанных типов

Рассмотрим следующие методы:

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<?>)

Другие вопросы по тегам