2016-10-25 9 views
1

У меня следующий код:Generics: Почему кастинг с подстановочным знаком и типом наоборот разрешен в параметре параметров метода?

public static void swap(List<?> list) { 
    swapHelper(list); //1 
} 

private static <E> void swapHelper(List<E> list) { 
    swap(list); //2 
} 

{ 
    List<?> tW = new ArrayList<>(); 
    List<E> tE = new ArrayList<>(); 

    tW = tE; // 3 
    tE = tW; // 4 
} 

В строке кода 1 и 2 компилируется успешно, не значит ли это: я могу назначить ссылки из List<?> в том, что из List<E> и наоборот? Если да, то почему строка номер 4 не компилируется.

ответ

-2

И <?> и <E> - неизвестные типы; но все List<?> s имеют элементы типа, поэтому вы можете вызвать метод, параметр которого равен List<E>, потому что есть какой-то неизвестный тип, который соответствует ему.

Обратите внимание, что вы не можете сделать это:

public static void swap(Object object, List<?> list) { 
    swapHelper(object, list); // Compiler error: object not in bounds of list. 
} 

private static <E> void swapHelper(E object, List<E> list) { 
    swap(object, list); // OK. 
} 

, потому что теперь вы не знаете, если Object находится в пределах List<?>.

Также вы можете добавлять новые ненулевые значения в списке:

private static <E> void swapHelper(List<E> list) { 
    list.add(new E()); // Can't create an instance of type variable. 
    swap(list); 
} 

, но вы можете добавить значения, которые вы берете из списка, так как они, как известно, в пределах списка:

private static <E> void swapHelper(List<E> list) { 
    list.add(list.get(0)); 
    swap(list); 
} 

так типобезопасен сделать вызывать оригинальную swapHelper из swap, так как вы не можете вызвать то, что не является преобразуемым E (независимо от того, что тип) в списке.

Аналогично с tW и tE:

  • Если вы назначаете tW = tE, вы не можете ничего добавлять к tW кроме null, так что вы не можете поставить tE в состоянии, в котором он содержит ничего, кроме случаев, от E.
  • Если вам было разрешено назначить tE = tW, вы можете получить добавить ненулевые экземпляры E в tE. Это может означать, что вы могли бы добавить экземпляр неправильного класса в tW, что потенциально может привести к ошибкам типа времени выполнения. Таким образом, это назначение запрещено.

Помните, что назначение списка не вызывает список должен быть скопирован: если вы назначаете tE = tW, то tE == tW, поэтому все изменения, внесенные в tE также видны через tW, так как они же экземпляр.

+0

Downvoter: помочь объяснить? –

 Смежные вопросы

  • Нет связанных вопросов^_^