Java 7中的菱形运算符允许如下代码:
List list = new LinkedList<>();
但是,在Java 5/6中,我可以简单地编写:
List list = new LinkedList();
我对类型擦除的理解是这些完全相同。 (无论如何,泛型都会在运行时删除)。
为什么要打扰钻石呢? 它允许哪些新功能/类型安全? 如果它没有产生任何新功能,为什么他们将其称为功能? 我对这个概念的理解有缺陷吗?
#1楼
此行导致[unchecked]警告:
List list = new LinkedList();
因此,问题发生了变化:为什么仅在创建新集合时才自动取消[unchecked]警告?
我认为,然后添加<>功能会更加困难。
UPD :我还认为,如果合法地使用原始类型“仅用于几件事”会造成混乱。
#2楼
您的理解有些瑕疵。 Diamond运算符是一个不错的功能,因为您不必重复自己的操作。 在声明类型时一次定义类型是有意义的,但是在右侧再次定义它是没有意义的。 DRY原理。
现在来解释有关定义类型的所有模糊性。 您是对的,该类型在运行时已删除,但是一旦您想从具有类型定义的列表中检索某些内容,就可以在声明该列表时将其恢复为您定义的类型,否则它将丢失所有特定功能并且仅具有对象功能,除非您将检索到的对象转换为原始类型,否则有时会非常棘手,并导致ClassCastException。
使用List list = new LinkedList()将获得原始类型警告。
#3楼
当您写List list = new LinkedList(); ,编译器会产生“未经检查”的警告。 您可能会忽略它,但是如果您过去曾经忽略这些警告,则可能还会错过一条警告消息,该警告通知您有关实型安全问题。
因此,最好编写一个不会生成额外警告的代码,并且菱形运算符允许您以便捷的方式进行操作,而无需不必要的重复。
#4楼
Diamond运算符的目的只是在声明泛型类型时减少代码的类型。 它对运行时没有任何影响。
如果您在Java 5和6中指定,则唯一的区别是
List list = new ArrayList();
是您必须在list指定@SuppressWarnings("unchecked") (否则,您将获得未选中的强制转换警告)。 我的理解是,钻石运营商正在努力使开发变得更容易。 与泛型的运行时执行完全无关。
#5楼
与问题
List list = new LinkedList();
是在左侧,您使用的是通用类型List ,而在右侧,您使用的是原始类型LinkedList 。 Java中的原始类型实际上仅存在于与前泛型代码的兼容性,并且除非绝对必要,否则绝对不能在新代码中使用。
现在,如果Java从一开始就具有泛型,并且没有诸如LinkedList类的类型,而该类型最初是在具有泛型之前创建的,则它可能已经做到了,这样泛型类型的构造函数会自动从Java推断其类型参数。如果可能的话,在作业的左侧。 但事实并非如此,为了向后兼容,必须对原始类型和泛型类型进行不同的处理。 这使得他们需要采取一种稍微不同但同样方便的方式来声明泛型对象的新实例,而不必重复其类型参数……菱形运算符。
就您的List list = new LinkedList()的原始示例而言,编译器会为该分配生成警告,因为它必须这样做。 考虑一下:
List strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List integers = new LinkedList(strings);
存在泛型以提供编译时保护以防止做错事。 在上面的示例中,使用原始类型意味着您没有获得此保护,并且在运行时会收到错误消息。 这就是为什么您不应该使用原始类型的原因。
// Not legal since the right side is actually generic!
List integers = new LinkedList<>(strings);
但是,菱形运算符允许将赋值的右侧定义为具有与左侧相同类型参数的真实泛型实例,而不必再次键入这些参数。 它使您可以与使用原始类型几乎相同的工作来保持泛型的安全。
我认为关键要理解的是原始类型(不带<> )不能与泛型类型相同。 声明原始类型时,不会获得任何好处和泛型的类型检查。 您还必须记住, 泛型是Java语言的通用组成部分 ……它们不仅仅适用于Collection的no-arg构造函数!