2015-09-07 2 views
7

Я читал, что, поскольку Java 7, создавая Коллекции с указанием типа с правой стороны, как в первом утверждении, является плохим стилем, потому что компилятор может вывести тип с левой стороны.Почему тип не выводится при выходе из оператора генериков

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

Мой вопрос при инициализации списка, как это, компилятор не находит тип, и я получаю непроверенное предупреждение типа:

List<Integer> myList = new ArrayList(); 

ответ

12

Компилятор не Infer типа, потому что вы инстанцировании сыройArrayList. Но он достаточно умен, чтобы предупредить вас, что при работе с этим (необработанным) объектом могут возникнуть проблемы.

Следует упомянуть причину этого предупреждения. Из-за type erasure параметрическая информация (<Integer>) о List полностью исчезнет во время выполнения, когда переменная будет содержать элементы типа Object. Рассмотрим этот фрагмент:

List rawList = new ArrayList(); //raw list 
rawList.add(new String("hello")); 
rawList.add(new Double(12.3d)); 
List<Integer> intList = rawList; // warning! 

Этот фрагмент будет скомпилирован, но будет генерировать несколько предупреждений. Имея необработанный список (rawList), вы можете добавить в список любой непримитивный тип, включая String, Double и т. Д. Но при назначении этой коллекции списку, который указан для целых чисел , то это проблема. В Runtime вы получите ClassCastException при попытке получить некоторый элемент из intList, который должен быть Integer, но на самом деле это String или что-то еще.

Короткий рассказ длинного - не смешивать сырые типы с дженериками!

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

List<Integer> list = new ArrayList<>(); //¯\_(ツ)_/¯ 
            ↑↑ 
9

Потому что вы забыли угловые скобки (так называемого оператор бриллианта).

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

Это синтаксически эквивалентно

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

но отличается от

List<Integer> myList = new ArrayList(); 

В 3-м вы говорите, что правая часть является исходным типом означая ArrayList может содержать любой объект (не только Integer). Дженерики просто компилируют время и скомпилируются в роли типа save.

+0

Почему это дает компилятору больше информации, чем список MyList = новый ArrayList(), так как на левой стороне родовой информации Availabe – PKuhn

+0

Поскольку оба семантический различны. Опущение типа в алмазе - это просто синтаксическая идея. – lschuetze

2

Вы можете использовать оператор алмазного вывести тип из декларации, как указаны в JLS (§15.9),.

Выражение создания экземпляра класса определяет класс быть обработан, возможно, следует аргументы типа (§4.5.1) или алмаз («<>»), если класс будучи реализованным является общим (§8.1.2), за которым следует (возможно, пустой) список аргументов фактического значения конструктору.

List<Integer> myList = new ArrayList<>(); 
7

От https://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html:

Обратите внимание, что воспользоваться автоматическим умозаключения типа во время родовой класса экземпляра, необходимо указать алмаз. [...] Конструктор HashMap() относится к HashMap необработанному типу, а не Map<String, List<String>>.