类型推断:Java7类型参数

类型推断:Java7类型参数,java,generics,java-7,type-inference,variable-declaration,Java,Generics,Java 7,Type Inference,Variable Declaration,今天我们讨论了Java7在我们公司的优势。因为Java7,所以有可能定义以下行 Map<String, List<String>> myMap = new HashMap<String, List<String>>(); 作为 我们就上述主题进行了长时间的讨论。我们中的一些人认为这是类型推断,就像C中的var关键字一样,类型将在运行时计算,其他人认为这只是声明某个变量的一种更简单的方法,并且没有推断,因为编译时上下文知道类型 请提供澄清。这项技术

今天我们讨论了Java7在我们公司的优势。因为Java7,所以有可能定义以下行

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

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

请提供澄清。这项技术是如何工作的

编辑: Oracle官方文档没有提供关于这方面的精确文档

实际上,这是类型推断

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

从:

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

更多信息:

我们中的一些人认为这是类型推断,就像C中的var关键字一样,类型将在运行时计算,其他人认为这只是声明某个变量的一种更简单的方法,并且没有推断,因为编译时上下文知道类型

泛型类的定义格式如下:

class name<T1, T2, ..., Tn> { /* ... */ }
就使用泛型声明某个类的语法而言,如下所示:

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

OR

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

在案例I中,右侧声明是冗余的,可以从对象的左侧声明中推断出来,因此在右侧写入被认为是不必要的,因为Java7首先注意到,新HashMap和新HashMap以及新HashMap之间编译的字节码绝对没有区别,因为它们在类型擦除后是相同的。因此,如果在对象创建中有任何放在括号中的内容,则只在编译时使用

有人说,使用菱形运算符,编译器可以推断其中的类型。但是,让我们考虑编译器为什么需要推断这一点。为什么编译器需要知道其中的内容

如果您调用的构造函数采用了K或V类型的一些参数,那么该类型在括号中很重要,因为它充当可以作为参数传递的对象类型的约束。在这种情况下,编译器应该推断它


但是,在问题中,如果调用的构造函数没有参数,编译器实际上不需要知道括号中的内容-编译器知道与否没有区别,因为它不需要它来生成字节码,我们知道存在一些可以工作的类型,没有使编译失败的参数类型。因此,在这种情况下,如果编译器不想进行推断,它就有可能不进行推断。

这是类型推断。有关其工作原理的详细信息,您需要阅读Java语言规范。相关的Oracle官方文档在这里:-更具体地说,在这里:对于Java 7,无论如何。而且,类型推断总是在编译时发生,而不是在运行时发生。绝对明白。请记住,参数化类型(又称泛型)在编译过程中会被删除。因此,它们没有经过运行时类型检查。编译器确实会检查它们,但在编译时会删除它们。@EdwinBuck正确,但与此问题相关的意义是什么?即使没有发生类型擦除,答案也不会改变。类型推断仍然会发生。类型擦除总是发生在泛型上。这就是为什么不能对它们进行任何运行时类型推断,这就是为什么这条语句与菱形推断是否发生在运行时有关,而菱形推断是问题中的一个人假设的一部分
class name { /* ... */ }
-- (Case I)
Map<String, List<String>> myMap = new HashMap<String, List<String>>(); 

OR

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