Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using diamond operator in Java 7

Tags:

java

generics

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.

like image 959
Akash Goel Avatar asked Jun 20 '14 20:06

Akash Goel


People also ask

What is Diamond inference in Java?

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.

What is raw type in Java?

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>.

What is the generic in Java?

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.


2 Answers

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.

like image 174
Thorn G Avatar answered Sep 22 '22 11:09

Thorn G


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.

like image 30
Joseph Nuthalapati Avatar answered Sep 20 '22 11:09

Joseph Nuthalapati