Type Inference: Java 7 Type Parameters

↘锁芯ラ 提交于 2019-12-23 04:45:56

问题


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


回答1:


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:

  • Type inference from the Java Tutorials



回答2:


"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




回答3:


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.



来源:https://stackoverflow.com/questions/25139508/type-inference-java-7-type-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!