类型推断: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()之间,编译的字节码完全没有区别,因为它们在类型擦除后是相同的。 因此,无论您在对象创建中放置括号(如果有),只能在编译时使用。

有人说,对于钻石操作符,编译器会“推断”那里的类型。 但是让我们考虑为什么编译器需要“推断”这一点。 为什么编译器需要知道那里有什么?

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

但是,在问题的情况下,你在调用没有参数的构造函数时,编译器并不需要知道括号中的内容 – 编译器是否知道它没有区别,因为1)它确实不需要它来生成字节码,2)我们知道存在一些可行的类型(没有参数类型使编译失败)。 因此,在这种情况下,编译器可能无法“推断”它是否不想。