Java7中的菱形运算符允许如下代码:
List<String> list = new LinkedList<>();
然而,在Java 5/6中,我可以简单地编写:
List<String> list = new LinkedList();
我对类型擦除的理解是,它们完全相同.(无论如何,泛型会在运行时被删除).
为什么要费心go 买钻石呢?它允许哪些新功能/类型安全性?如果它没有产生任何新的功能,为什么他们要把它作为一个特性提到呢?我对这个概念的理解有问题吗?
Java7中的菱形运算符允许如下代码:
List<String> list = new LinkedList<>();
然而,在Java 5/6中,我可以简单地编写:
List<String> list = new LinkedList();
我对类型擦除的理解是,它们完全相同.(无论如何,泛型会在运行时被删除).
为什么要费心go 买钻石呢?它允许哪些新功能/类型安全性?如果它没有产生任何新的功能,为什么他们要把它作为一个特性提到呢?我对这个概念的理解有问题吗?
问题在于
List<String> list = new LinkedList();
左边是generic型List<String>
,右边是raw型LinkedList
.Java中的原始类型实际上只是为了与泛型之前的代码兼容而存在的,除非
现在,如果Java从一开始就有泛型,并且没有最初在有泛型之前创建的类型,比如LinkedList
,那么它可能已经创建了泛型类型,以便泛型类型的构造函数在可能的情况下从赋值的左侧自动推断其类型参数.但事实并非如此,它必须以不同的方式对待原始类型和泛型类型,以实现向后兼容性.这就使得他们需要用一种slightly different但同样方便的方式来声明泛型对象的新实例,而不必重复其类型参数...钻石操作员.
对于List<String> list = new LinkedList()
的原始示例,编译器会为该赋值生成警告,因为它必须.考虑一下:
List<String> strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);
泛型的存在是为了提供编译时保护,防止出错.在上面的示例中,使用raw类型意味着您没有得到这种保护,并且在运行时会出现错误.这就是为什么不应该使用原始类型.
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
然而,菱形运算符允许将赋值的右侧定义为真正的泛型实例,其类型参数与左侧相同...无需再次输入这些参数.它允许你像使用原始类型一样努力保持泛型的安全性.
我认为需要理解的关键是,原始类型(没有<>
)不能与泛型类型一样对待.当您声明一个原始类型时,您不会得到泛型的好处和类型判断.你也要记住generics are a general purpose part of the Java language...它们不仅仅适用于Collection
s的无参数构造函数!