为什么在 Java 7 中将菱形运算符用于类型推断?

List<String> list = new ArrayList();将导致编译器警告。

但是,以下示例在编译时没有任何警告:List<String> list = new ArrayList<>();

我很好奇为什么需要引入钻石操作员。如果类型参数不存在,为什么不直接在构造函数上进行类型推断(因为它已经为java中的静态方法完成了,并被google guava等集合库所利用)

编辑:使用毫摩尔斯答案作为起点,我研究了类型擦除实际上是什么,它不仅仅是删除所有类型信息。编译器实际上做得更多(从官方文档复制):

  • 如果类型参数未绑定,则将泛型类型中的所有类型参数替换为其边界或 Object。因此,生成的字节码仅包含普通类、接口和方法。
  • 如有必要,插入类型转换以保持类型安全。
  • 生成桥接方法以保持扩展泛型类型中的多态性。

答案 1

最终的答案必须来自设计该功能的人,但我假设这是为了将其与使用原始类型区分开来,后者使编译器为了兼容性而做一些完全不同的事情。其中包含原始类型的表达式的处理方式与涉及泛型的表达式略有不同,在此 SO 问题中可以找到一个示例:泛型搞砸了不相关的集合


答案 2

Java开发人员非常努力地避免改变现有程序的行为。 进行编译,并创建一个原始 ArrayList。如果对它应用类型推断,结果将是 ,更改其行为并可能导致程序中其他位置的运行时错误。List<String> list = new ArrayList();ArrayList<String>

============================================================================

经过进一步的考虑,以及@millimoose的评论,我看到行为的变化将是初始值设定项的本地,并在编译时检测到。请考虑以下程序:

import java.util.ArrayList;
import java.util.List;


public class Test {
  public static void main(String[] args) throws Exception {
    List<Integer> integers = new ArrayList<Integer>();
    integers.add(Integer.valueOf(3));
    integers.add(Integer.valueOf(4));
    List<String> list = new ArrayList(integers);
    System.out.println(list);
  }
}

如果没有类型推断,它将运行并打印 ,尽管包含整数引用的 a 是不理想的情况。[3, 4]List<String>

使用类型推断,它不会编译,因为在创建 .ArrayList(Collection<? extends E> c)List<Integer>ArrayList<String>


推荐