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();
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<>(); //¯\_(ツ)_/¯
↑↑
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.
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 theHashMap
raw type, not theMap<String, List<String>>
type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With