Prior to Java 7 the syntax below was used to create an ArrayList,
ArrayList<Integer> ints = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7));
But since Java 7 we can omit the generic type in the constructor i.e.,
ArrayList<Integer> ints = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
But when I tried to do something like,
ArrayList<Number> nums = new ArrayList<>(Arrays.asList(1,2,3,4,4,5.5,6.6,7.7));
I get an error, but when I mention the generic type on right side i.e.,
ArrayList<Number> nums = new ArrayList<Number>(Arrays.asList(1,2,3,4,5.5,6.6,7.7));
The code works perfectly. What could be the reason behind this ?
Thanks in Advance.
The diamond operator – introduced in Java 1.7 – adds type inference and reduces the verbosity in the assignments – when using generics: List<String> cars = new ArrayList<>(); The Java 1.7 compiler's type inference feature determines the most suitable constructor declaration that matches the invocation.
A raw type is a name for a generic interface or class without its type argument: List list = new ArrayList(); // raw type. Instead of: List<Integer> listIntgrs = new ArrayList<>(); // parameterized type. List<Integer> is a parameterized type of interface List<E> while List is a raw type of interface List<E>.
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
Arrays.asList
is a generic method, so technically, it can be invoked as:
Arrays.<Number> asList(1, 2, 3);
Even before Java 7, the language could do some limited inference to eliminate this when the left-hand side was known, as in
final List<Number> nums = Arrays.asList(1, 2, 3);
It looks like you stumbled onto an edge case where the two types of inference cannot be successfully combined, where the diamond inference and generic method inference don't get along. I'm sure the JLS sheds more light on this as well if you were to dig through it.
Java Generics are Invariant whereas Arrays are Covariant.
If generics in Java were covariant, if A
is a subtype of B
, then List[A]
is a subtype of List[B]
. But it is not the case in Java. ( Scala has a covariance implementation. In Scala, if B
extends A
, then List[B]
extends List[A]
)
But String[]
is subtype of Object[]
Hence an ArrayList<Double>
cannot be cast to an ArrayList<Number>
as in your case.
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