2009-07-23 2 views
2

этот код компилируется в порядке и при выполнении произведет «004b», как это происходит, почему он не создает исключение classcastException.java Generics проблема компиляции устаревания

public static void append(List list) { 
    list.add("004b"); 
} 

public static void main(String[] args) { 
    List<Integer> intList = new ArrayList<Integer>(); 
    append(intList); 
    System.out.println(intList.get(0)); 
} 
+1

Я бы не сказал, что он компилируется отлично - компилятор должен дать вам предупреждение об использовании типа сырого списка. Если вы не учтете это предупреждение, ну, вы программист :) – extraneon

ответ

2

Поскольку дженерики реализованы на Java посредством стирания типов; то есть нет информации о времени выполнения для типов, просто при необходимости отбрасывает. Если вы должны были сказать

Integer i = intList.get(0); 

тогда было бы компилировать

Integer i = (Integer) intList.get(0); 

и бросить исключение в класс произнесения.

Поскольку System.out.println() принимает объект в качестве аргумента, литье не требуется.

3

Вы вызов System.out.println(Object) переопределения, так как тип intList.get(0) является Integer и нет Integer -специфических перегрузок. После компиляции информация о типе стирается, оставляя возвращаемый тип просто Object для intList.get(0) после стирания типа. Это соответствует ожидаемому типу для вызова функции println(Object), поэтому выполнение каста не выполняется, и никакое исключение не генерируется.

+0

Если тип 'intList' был' List ', было бы выбрано исключение. –

1

Где вы ожидаете, как выглядит ClassCastException?

Это не произойдет, когда вы вызываете append, потому что append использует необработанный список.

Это не произойдет, если вы вызываете println, потому что println принимает объект, и поэтому не выполняется неявное кастинг.

Возможно, было немного удивительно, что разрешение перегрузки выбирает println (Object), а не println (int) (потому что эта перегрузка существует). Это связано с тем, что при определении перегрузки (в основном для обратной совместимости) автобоксинг имеет крайне низкий приоритет.

+0

umm ... зачем ему выбирать println (String)? «intList.get (0)» имеет тип Integer, и поэтому, естественно, он выбирает println (Object) – newacct

+0

Да, я почему-то запутался. Должно быть исправлено сейчас. –

4

Предложения:

  1. Не смешивать сырые и родовое набрав
  2. Включите ваш Java компилятор общего типа предупреждений. Это расскажет вам о вашем неправильном коде.
  3. Если вы используете тип «проверенной коллекции» (например, созданный с использованием Collections.checkedList (...)), вы получите исключение, если вы введете в коллекцию неверно типизированный объект.
Смежные вопросы