2015-05-18 5 views
7

я наткнулся на следующий код, простой пример добавления элементов ListПозволяет ли ArrayList <Integer> добавить строку?

List list = new ArrayList<Integer>(); 
    ListIterator<Integer> litr = null; 
    list.add("A"); 

    list.add("1"); 

    list.add(5); 

    litr = list.listIterator(); 
    while(litr.hasNext()){ 
     System.out.println("UIterating " + litr.next()); 
    } 

Я ожидал, что это бросить ClassCastException, а он писал на консоль

A 
1 
5 

, который выглядит странно , Когда я попытался:

List<Integer> list = new ArrayList<Integer>(); 

У меня ошибка времени компиляции.

Я был бы признателен, если кто-то может объяснить, как String объекты добавляются к ArrayList

+4

http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – CupawnTae

+4

http://stackoverflow.com/questions/2770321/what-is-a-raw -type-and-why-shouldnt-we-use-it – Reimeus

+1

Я могу подвести итог в одном предложении: «В Java дженерики выполняются только во время компиляции». Сказав это, Java выдает вам предупреждение об использовании необработанных типов по этой причине. – Powerlord

ответ

4

Вы назначен новый ArrayList в нетипизированный список. Ограничения общего типа не относятся к нетипизированному списку, это позволит вам помещать в него все, что вам нужно. Компилятор не отслеживает, что ваш нетипизированный список ссылается на то, что было объявлено с помощью универсального типа.

В любом случае это не вызовет ClassCastException, генерики влияют только на компиляцию. Во время выполнения

Случая, когда вы кладете тип на переменном список:

List<Integer> list = new ArrayList<Integer>(); 

является предпочтительным, он должен сгенерировать ошибку компиляции, сообщающую, вы кладете неправильный тип в коллекции.

Там есть описание того, как наследство, не универсальный код и общий код в this article взаимодействия:

В правильном общем коде, коллекция всегда будет сопровождаться параметром типа. Когда общий тип типа Collection используется без параметра типа, он называется сырым типом.

Первым инстинктом большинства людей является то, что коллекция действительно означает Collection<Object>. Однако, как мы видели ранее, небезопасно передавать Collection<Part> в месте, где требуется Collection<Object>. Точнее сказать, что тип Collection обозначает коллекцию некоторого неизвестного типа, как и Collection<?>.

Но подождите, это тоже не так! Рассмотрим вызов getParts(), который возвращает коллекцию. Затем ему присваивается значение k, которое равно Collection<Part>. Если результатом вызова является Collection<?>, назначение будет ошибкой.

В действительности, назначение является законным, но оно генерирует непроверенное предупреждение. Предупреждение необходимо, потому что факт заключается в том, что компилятор не может гарантировать его правильность. У нас нет способа проверить устаревший код в getAssembly(), чтобы убедиться, что действительно возвращенная коллекция представляет собой коллекцию деталей. Тип, используемый в коде, представляет собой Collection, и каждый может законно вставлять все виды объектов в такую ​​коллекцию.

Так, разве это не ошибка? Теоретически, да; но на самом деле, если общий код будет использовать устаревший код, это должно быть разрешено. Это зависит от вас, программист, чтобы убедиться, что в этом случае назначение безопасно, потому что контракт getAssembly() говорит, что он возвращает коллекцию частей, хотя подпись типа не показывает этого.

+0

Просто FYI: вы должны поместить кодовые блоки вокруг кода в цитате. В противном случае вы не видите, что одна из Коллекций - «Коллекция ' – Powerlord

+0

@Powerlord: right, thanks –

+0

@NathanHughes Спасибо за ваш ответ. Получил представление о нетипизированном списке и исходной коллекции –

1

Это возможно из-за того, как дженерики реализуются в Java - с помощью type erasure, и потому, что Java поддерживает raw types для обратной совместимости со старыми версиями Java (1.4 и старше).

Дженерики существуют только в вашем исходном коде. Компилятор использует их для проверки типов во время компиляции, но затем отбрасывает генерики. Во время выполнения List<Integer> представляет собой всего лишь List объектов, и он не знает, что это список, который должен содержать только Integer объектов.

Java поддерживает использование необработанных типов, таких как List, вместо List<Integer> для обратной совместимости со старыми версиями. Когда вы используете необработанный тип, как вы это делаете в своем коде выше, вы получаете предупреждение компилятора. Вы не должны использовать необработанные типы в новом коде - только когда-либо используйте их, когда вам нужно иметь дело со старым кодом, который вы не можете изменить.

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

Поскольку List во время выполнения ничего не знает о типе, который должен иметь его элемент, он ничего не проверяет, поэтому вы не получите ClassCastException.

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