2015-09-07 16 views
7

Przeczytałem, że ponieważ Java 7, tworzenie kolekcji z określeniem typu po prawej stronie, tak jak w pierwszej instrukcji, jest złym stylem, ponieważ kompilator może wywnioskować typ z lewej strony.Dlaczego typ nie jest wywnioskowany podczas odstawiania operatora generics

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

Moje pytanie jest, gdy inicjowanie listę tak, kompilator nie odnaleźć typ i dostaję niezaznaczone ostrzeżenia typu:

List<Integer> myList = new ArrayList(); 

Odpowiedz

12

Kompilator nie wywnioskować typ, bo jesteś uruchamianiu tego surowegoArrayList. Ale jest wystarczająco inteligentny, aby ostrzec cię, że mogą wystąpić problemy podczas pracy z tym (surowym) obiektem.

Warto wspomnieć o przyczynie tego ostrzeżenia. Z powodu type erasure, parametryczna informacja (<Integer>) o wartości List zniknie całkowicie w środowisku wykonawczym, gdy zmienna będzie zawierać elementy typu Object. Rozważ ten fragment:

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

Ten fragment zostanie skompilowany, ale wygeneruje kilka ostrzeżeń. Mając listę nieprzetworzoną (rawList), można dodać do listy dowolny typ niepochowany, w tym String, Double itp. Jednak przy przypisywaniu tej kolekcji do listy, która jest określona jako liczba całkowita o wartości , jest ona liczbą całkowitą. problem. W środowisku wykonawczym otrzymasz kod ClassCastException podczas próby pobrania elementu z intList, który ma być Integer, ale w rzeczywistości jest to String lub coś innego.

Krótka historia - Nie mieszaj surowych typów z generics!

W twoim przypadku, kompilator byłoby ewentualnie zostały wywnioskować typ, jeśli użyłeś diament:

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

Bo zapomnieli kątowniki (zwany operatorem diament).

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

To składniowo równoważne

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

ale różni się

List<Integer> myList = new ArrayList(); 

w 3. Mówisz, że prawa strona jest surowy typ czyli ArrayList może posiadać każdy obiekt (nie tylko Integer). Generics są tylko czasem kompilacji i są kompilowane do rzutowania typu zapisu.

+0

Dlaczego to dać kompilator więcej informacji niż Lista mylist = new ArrayList(), ponieważ po lewej stronie jest informacja generic dostępnej – PKuhn

+0

Ponieważ oba są semantycznie różne. Pominięcie typu w bryle to tylko sugestia syntaktyczna. – lschuetze

2

Można użyć operatora diament wywnioskować typ z deklaracji określonych w JLS (§15.9),.

Wyrażenie tworzenie przykład klasy określa klasę do wystąpienia, a następnie, argumenty typu (§4.5.1) lub diamentu („<>”), gdy grupa jest instancja jest nazwą rodzajową (§8.1.2), a następnie (ewentualnie pusta) lista argumentów wartości rzeczywistej do konstruktora.

List<Integer> myList = new ArrayList<>(); 
Powiązane problemy