爪哇金刚石运算符(<>)的意义何在?

2022-08-31 04:27:00

java 7 中的菱形运算符允许如下代码:

List<String> list = new LinkedList<>();

然而,在Java 5/6中,我可以简单地写:

List<String> list = new LinkedList();

我对类型擦除的理解是,这些是完全相同的。(无论如何,泛型都会在运行时被删除)。

为什么要为钻石而烦恼呢?它允许哪些新功能/类型安全?如果它没有产生任何新功能,为什么他们提到它作为一个功能?我对这个概念的理解有缺陷吗?


答案 1

问题

List<String> list = new LinkedList();

在左侧,您使用的是泛型类型,而右侧则使用 原始类型 。Java 中的原始类型实际上只是为了与前泛型代码兼容而存在,除非您绝对需要,否则永远不应在新代码中使用。List<String>LinkedList

现在,如果 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语言的通用部分...它们不仅适用于 s 的无参数构造函数!<>Collection


答案 2

你的理解略有缺陷。钻石操作员是一个很好的功能,因为您不必重复自己。在声明类型时定义一次类型是有意义的,但是在右侧再次定义它是没有意义的。干燥原理。

现在解释一下关于定义类型的所有模糊。你是对的,类型在运行时被删除,但是一旦你想从具有类型定义的List中检索某些内容,你就会把它作为你在声明列表时定义的类型,否则它将丢失所有特定功能,并且只有Object功能,除非你将检索到的对象强制转换为它的原始类型,这有时可能非常棘手并导致ClassCastException。

使用将为您提供原始类型警告。List<String> list = new LinkedList()


推荐