java 7 中的菱形运算符允许如下代码:
List<String> list = new LinkedList<>();
但是在 Java 5/6 中,我可以简单地写:
List<String> list = new LinkedList();
我对类型删除的理解是这些是完全一样的。 (无论如何,泛型在运行时都会被删除)。
为什么要操心钻石呢?它允许哪些新功能/类型安全?如果它没有产生任何新功能,为什么他们会提到它作为一个特性?我对这个概念的理解有问题吗?
问题
List<String> list = new LinkedList();
是在左侧,您使用的是 generic 类型List<String>
在右侧您使用 raw 类型的位置 LinkedList
. Java 中的原始类型实际上只是为了与泛型前代码兼容而存在,并且不应该在新代码中使用,除非你绝对必须这样做。
现在,如果 Java 从一开始就有泛型而没有类型,例如 LinkedList
,它最初是在泛型之前创建的,它可能已经做到了,以便泛型类型的构造函数在可能的情况下自动从赋值的左侧推断其类型参数。但它没有,它必须区别对待原始类型和泛型类型以实现向后兼容性。这使得他们需要制作一种略有不同但同样方便的方式来声明通用对象的新实例,而不必重复其类型参数......菱形运算符。
就您的 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);
存在泛型以提供编译时保护以防止做错事。在上面的例子中,使用原始类型意味着你没有得到这种保护,并且会在运行时出错。这就是你不应该使用原始类型的原因。
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
然而,菱形运算符允许将赋值的右侧定义为具有与左侧相同类型参数的真正泛型实例......而无需再次键入这些参数。它允许您通过几乎与使用原始类型相同的努力来保持泛型的安全性。
我认为要理解的关键是原始类型(没有 <>
)不能与泛型类型一样对待。当你声明一个原始类型时,你没有得到泛型的任何好处和类型检查。您还必须记住,泛型是 Java 语言的通用部分...它们不仅仅适用于 Collection
的无参数构造函数。秒!
我是一名优秀的程序员,十分优秀!