Java 7中的钻石操作符有什么意义?

Java 7中的钻石操作符允许如下代码:

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

但是在Java 5/6中,我可以简单地写出:

List<String> list = new LinkedList();

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

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


与问题

List<String> list = new LinkedList();

在左侧,您使用的是泛型类型List<String> ,在右侧您使用的是原始类型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的无参数构造函数!


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

现在来解释关于定义类型的所有模糊问题。 你是对的,类型在运行时被移除,但是一旦你想从类型定义的列表中取出某些东西,你会在声明列表时将它返回为你定义的类型,否则它将失去所有特定的功能,对象的功能除非将检索到的对象转换为原始类型,这有时会非常棘手并导致ClassCastException。

使用List<String> list = new LinkedList()会为您提供rawtype警告。


该行会导致[unchecked]警告:

List<String> list = new LinkedList();

所以,这个问题转化为:为什么只有在创建新集合的情况下,[unchecked]警告才会被自动抑制?

我认为,添加<>功能将会非常困难。

UPD:我也认为如果合法使用原始类型“只是为了一些事情”会有一团糟。

链接地址: http://www.djcxy.com/p/73639.html

上一篇: What is the point of the diamond operator in Java 7?

下一篇: Why doesn't Java support unsigned ints?