类型推断:Java 7类型参数
今天我们谈到了Java 7在我们公司的优势。 从Java 7开始,可以定义以下行
Map<String, List> myMap = new HashMap<String, List>();
如
Map<String, List> myMap = new HashMap();
我们对上述主题进行了长时间的讨论。 我们中的一些人认为这是类型推断(如C#中的var
关键字),并且类型将在运行时计算,其他人认为它只是一种更简单的方式来声明某个变量并且没有推断,因为已知类型在编译时的上下文。
请提供澄清。 技术如何运作?
编辑:官方Oracle文档没有提供有关该文档的精确文档。 http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
实际上,它是类型推断。
菱形运算符( <>
)允许将赋值的右侧定义为具有与左侧相同类型参数的真正通用实例, 而无需再次键入这些参数 (因为编译器推断出类型(s) )从左侧)。
来自Angelika Langer的Generics FAQ :
它(菱形运算符)表示在新表达式中用于类型推断的空尖括号。
更多信息:
- 从Java教程中输入推断
“我们中的一些人认为这是类型推断(如C#中的var关键字),类型将在运行时计算,其他人认为这只是一种更简单的方式来声明某个变量并且没有推断,因为类型是在编译时被上下文所知。“
参考:使用以下格式定义generics类:
class name { /* ... */ }
由尖括号(<>)分隔的类型参数部分跟在类名后面。 它指定类型参数(也称为类型变量)T1,T2,…和Tn。
在编译时,类型参数被删除,并通过类型擦除过程转换为原始类型 ,意味着上述声明将转换为:
class name { /* ... */ }
就使用generics声明某些类的语法而言,如:
-- (Case I) Map> myMap = new HashMap>(); OR -- (Case II) Map> myMap = new HashMap<>();
case I
的右侧声明是多余的,这可以从一个对象的左侧声明推断出来,所以在右侧写入它认为是不必要的,因为Java7
首先请注意,在new HashMap
和new HashMap
和new HashMap()
之间,编译的字节码完全没有区别,因为它们在类型擦除后是相同的。 因此,无论您在对象创建中放置括号(如果有),只能在编译时使用。
有人说,对于钻石操作符,编译器会“推断”那里的类型。 但是让我们考虑为什么编译器需要“推断”这一点。 为什么编译器需要知道那里有什么?
如果你正在调用一个带有K
或V
类型参数的构造函数,那么类型在括号中很重要,因为它作为对象类型的约束,你可以作为参数传递。 在这种情况下,编译器应该推断它。
但是,在问题的情况下,你在调用没有参数的构造函数时,编译器并不需要知道括号中的内容 – 编译器是否知道它没有区别,因为1)它确实不需要它来生成字节码,2)我们知道存在一些可行的类型(没有参数类型使编译失败)。 因此,在这种情况下,编译器可能无法“推断”它是否不想。