类型推断:Java 7类型参数

时间:2014-08-05 13:00:59

标签: java generics java-7 type-inference variable-declaration

今天我们谈到了Java 7在我们公司的优势。从Java 7开始,可以定义以下行

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

作为

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

我们对上述主题进行了长时间的讨论。我们中的一些人认为这是类型推断(如C#中的var关键字)并且类型将在运行时计算,其他人认为它只是一种更简单的方式来声明某个变量并且没有推断,因为在编译时由上下文知道类型。

请提供说明。技术如何运作?

编辑: 官方Oracle文档未提供有关该文档的精确文档。 http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

3 个答案:

答案 0 :(得分:7)

实际上,类型推断。

菱形运算符(<>)允许将赋值的右侧定义为具有与左侧相同类型参数的真实通用实例,而无需再次键入这些参数(因为编译器从左侧推断类型)。

来自Angelika Langer's Generics FAQ

  

它(菱形运算符)表示在新表达式中用于类型推断的空尖括号。

更多信息:

答案 1 :(得分:0)

  

&#34;我们中的一些人认为这是类型推断(如C#中的var关键字),类型将在运行时计算,其他人认为它只是一种更简单的方式来声明一些变量和没有推论,因为在编译时上下文已知类型。&#34;

Ref: 泛型类使用以下格式定义:

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

由尖括号(&lt;&gt;)分隔的类型参数部分跟在类名后面。它指定类型参数(也称为类型变量)T1,T2,...和Tn。

在编译时,类型参数被删除,并且Raw Type的过程将其转换为Type Erasure,表示上述声明将转换为:

class name { /* ... */ }

就使用泛型声明某些类的语法而言:

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

OR

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

case I中,右侧声明是多余的,可以从对象的左侧声明推断,因此在右侧写入它认为不必要,因为Java7

答案 2 :(得分:0)

首先请注意,new HashMap<String, List<String>>()new HashMap<Integer, String>()new HashMap()之间的编译字节码完全没有区别,因为它们在类型擦除后是相同的。因此,无论您在对象创建中放置括号(如果有),只能在编译时使用。

有人说钻石操作员,编译器&#34;推断&#34;那里的类​​型。但是,让我们考虑一下为什么编译器需要推断&#34;这一点。为什么编译器需要知道那里有什么?

如果你正在调用一个带有KV类型参数的构造函数,那么类型在括号中很重要,因为它可以作为对象类型的约束,你可以传递给它论点。在这种情况下,编译器应推断它。

但是,在问题中,你在调用没有参数的构造函数的情况下,编译器并不需要知道括号中的内容 - 编译器是否知道它没有区别,因为1 )它不需要它来生成字节码,2)我们知道存在一些可行的类型(没有参数类型使编译失败)。所以在这种情况下,编译器可能不会推断&#34;如果它不想。