-1

today we talked about advantages of Java 7 in our company. Since Java 7 there is the possibility to define following line

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

as

Map<String, List<String>> myMap = new HashMap<>();

We had a long discussion about the topic described above. Some of us had the opinion that this is type inference (like var keyword in C#) and the type will be computed at runtime, others thought it's only a simpler way to declare some variable and there is no inference, because the type of is known by the context at compile time.

Please provide clarification. How dows the technique work?

EDIT: Official Oracle Documentation provides no precise documentation about that. http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
agassner
  • 689
  • 8
  • 25
  • It's type inference. For full details of how it works, you need to read the Java Language Specification. – davmac Aug 05 '14 at 13:04
  • The relevant "Official Oracle Documentation" is here: http://docs.oracle.com/javase/specs/ - and more specifically here: http://docs.oracle.com/javase/tutorial/java/generics/types.html and http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.7 (for Java 7 anyway). – davmac Aug 05 '14 at 13:34
  • 1
    And, type inference _always_ occurs at compile time, not run time. See http://en.wikipedia.org/wiki/Type_inference – davmac Aug 05 '14 at 13:37

3 Answers3

7

Actually, it is type inference.

The diamond operator (<>), allows the right hand side of the assignment to be defined as a true generic instance with the same type parameters as the left hand side without having to type those parameters again (because the compiler infers the type(s) from the left hand side).

From the Angelika Langer's Generics FAQ:

It (the diamond operator) denotes the empty angle brackets that are used for type inference in new -expression.

More info:

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • 2
    Absolutely. Remember that parameterized types (aka Generics) are erased during compilation. So, it follows that they are not run-time-type-checked. The compiler does check them, but at compile time (after which they are then erased). – Edwin Buck Aug 05 '14 at 13:05
  • @EdwinBuck correct, but what is the significance in relation to this question? Even if type erasure did not occur the answer would not change. Type inference would still occur. – davmac Aug 05 '14 at 13:30
  • Type erasure always occurs on Generics. That's why you can't do any runtime type inference on them, which is why this statement has something to do with whether the diamond inference occurs at runtime (which is part of what one person in the question is supposing) – Edwin Buck Aug 05 '14 at 13:33
0

"Some of us had the opinion that this is type inference (like var keyword in C#) and the type will be computed at runtime, others thought it's only a simpler way to declare some variable and there is no inference, because the type of is known by the context at compile time."

Ref: A generic class is defined with the following format:

class name<T1, T2, ..., Tn> { /* ... */ }

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.

At compile time the type parameter is removed and it is converted to Raw Type by the process of Type Erasure, means the above declaration will be converted to:

class name { /* ... */ }

As far as syntax of declaring some class with generic is concerned like:

-- (Case I)
Map<String, List<String>> myMap = new HashMap<String, List<String>>(); 

OR

-- (Case II)
Map<String, List<String>> myMap = new HashMap<>();

In case I the right hand side declaration is redundant, which can be inferred from left hand side declaration of an object, so writing on right hand side it considered unnecessary since Java7

Vishrant
  • 15,456
  • 11
  • 71
  • 120
0

First note that, there is absolutely no difference in compiled bytecode between new HashMap<String, List<String>>() and new HashMap<Integer, String>() and new HashMap(), because they are the same after type erasure. So whatever you put in brackets (if any) in the object creation is only used at compile-time.

Some people say that with the diamond operator, the compiler "infers" the type that goes in there. But let's consider why the compiler needs to "infer" this at all. Why does the compiler need to know what goes in there?

If you are calling a constructor that took some parameters of type K or V, then the type goes in brackets matters because it acts as a constraint on the type of object you can pass as the argument. In this case, the compiler should infer it.

However, in the case in the question, where you are calling a constructor with no parameters, the compiler does not really need to know what goes in the brackets -- it makes no difference whether the compiler knows or not, because 1) it does not need it to generate the bytecode, and 2) we know that there exists some type that will work (there is no parameter type to make the compilation fail). So in this case, it would be possible for a compiler to not "infer" if it doesn't want to.

newacct
  • 119,665
  • 29
  • 163
  • 224