今天我们谈到了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
答案 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;这一点。为什么编译器需要知道那里有什么?
如果你正在调用一个带有K
或V
类型参数的构造函数,那么类型在括号中很重要,因为它可以作为对象类型的约束,你可以传递给它论点。在这种情况下,编译器应推断它。
但是,在问题中,你在调用没有参数的构造函数的情况下,编译器并不需要知道括号中的内容 - 编译器是否知道它没有区别,因为1 )它不需要它来生成字节码,2)我们知道存在一些可行的类型(没有参数类型使编译失败)。所以在这种情况下,编译器可能不会推断&#34;如果它不想。