Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why type is not inferred when leaving away generics operator [duplicate]

Tags:

java

generics

I read that since Java 7, creating Collections with specifying the type on the right side like in the first statement is bad style because the compiler can infer the type from the left side.

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

My question is when initializing the list like this, the compiler does not find the type and I get an unchecked type warning:

List<Integer> myList = new ArrayList(); 
like image 746
PKuhn Avatar asked Sep 07 '15 12:09

PKuhn


3 Answers

The compiler doesn't infer the type, because you're instantiating a raw ArrayList. But it's smart enough to warn you that there might be problems when working with this (raw) object.

It's worth mentioning the reason behind this warning. Due to the type erasure, the parametric information (<Integer>) about the List will be completely gone at Runtime, when the variable would hold elements of type Object. Consider this snippet:

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

This snippet will compile, but will generate few warnings. Having a raw list (rawList), you can add any non-primitive type to the list, including String, Double, etc. But when assigning this collection to a list, which is specified to hold only integers, then this is a problem. At Runtime you'll get a ClassCastException when trying to fetch some element from the intList, which is supposed to be an Integer, but in reality is a String or something else.

Long story short - do not mix raw types with Generics!

In your case, the compiler would possibly have inferred the type, if you have used the diamond:

List<Integer> list = new ArrayList<>(); //¯\_(ツ)_/¯
                                  ↑↑
like image 167
Konstantin Yovkov Avatar answered Oct 19 '22 09:10

Konstantin Yovkov


Because you have forgotten the angle brackets(called diamond operator).

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

This is syntactically equivalent to

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

but different to

List<Integer> myList = new ArrayList();

In the 3rd you are saying that the right side is a raw type meaning the ArrayList can hold every object (not only Integer). Generics are just compile time and are compiled into save type casts.

like image 44
lschuetze Avatar answered Oct 19 '22 10:10

lschuetze


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

Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond. [...] The HashMap() constructor refers to the HashMap raw type, not the Map<String, List<String>> type.

like image 25
sp00m Avatar answered Oct 19 '22 09:10

sp00m