java - 菱形运算符的java 7重点是什么?

  显示原文与译文双语对照的内容

java 7中的菱形操作符允许如下代码:


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

但是在 Java 5中,我可以简单地编写:


List<String> list = new LinkedList();

我对类型擦除的理解是完全相同的。 ( 通常在运行时删除泛型) 。

为什么要用? 它允许哪些新的功能/类型安全? 如果它没有产生任何新的功能,为什么他们会把它当作一个特性? 我对这个概念的理解有缺陷?

时间:

问题有


List<String> list = new LinkedList();

是左边,你使用的是通用类型 List<String> 在右边你正在使用生 LinkedList 类型。 Java中的原始类型只存在于与pre-generics代码兼容的情况下,除非你绝对必须使用。

现在,如果Java有一个泛型,并且没有类型,比如 LinkedList,比如,那么在泛型之前,它可能会自动地从赋值的left-hand一侧推断出类型参数,如果可能的话。 但它没有,并且它必须对原始类型和泛型类型进行不同的向后兼容。 ,所以他们需要略有不同,但同样方便,声明一个新实例的一个通用的对象,而不必重复它的类型参数。 菱形操作符。

至于你的原始例子 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);

泛型提供了compile-time保护来防止出错。 在上面的示例中,使用原始类型意味着你没有得到这个保护,并且在运行时将得到一个错误。 这就是为什么不使用原始类型。


//Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

但是,diamond运算符允许赋值的右边定义为一个具有与左侧相同类型参数的真正通用实例。 不必再次键入这些参数。 它允许你用来保证泛型的安全几乎与使用原始类型相同。

我认为需要理解的关键是原始类型( 没有 <> ) 不能与泛型类型相同。 当你声明原始类型时,你不会得到泛型的好处和类型检查。 你还必须记住,泛型是Java语言的通用部分。 他们不只是适用于 Collection no-arg构造函数的年代!

你的理解有点有瑕疵。 菱形操作符是一个不错的特性,因为你不必重复自己。 在声明类型时定义类型是有意义的,但在右侧定义它没有意义。 干燥原理。

现在解释关于定义类型的所有模糊。 在一个classcastexception,的类型是在运行时移除你是对的,但是一旦要检索了从一列以类型定义你获得的回报为你已经定义的类型在声明列表( 否则就失去了许多特定的特征,只承受的对象特征时,只是当你会将检索到的对象强制转换为它的原始类是可以有时是非常狡猾和 result.

使用 List<String> list = new LinkedList() 会得到rawType警告。

此行将导致 [unchecked] 警告:


List<String> list = new LinkedList();

问题转换:为什么 [unchecked] 警告不仅抑制自动的情况下创建新的集合?

我认为,添加 <> 特性会更加困难。

乌利希期刊指南:我也认为会有一团糟如果是合法使用'只是为了一些东西'原始类型。

理论上,diamond操作符允许你通过保存重复的类型参数来编写更紧凑的( 和可读性) 代码。 在实践中,它只是两个令人困惑的字符,给你一点帮助。 为什么?

  1. 没有理智的程序员在新代码中使用原始类型。 因此编译器可以简单地假定,通过编写任何类型参数,你都想推断它们。
  2. diamond操作符没有提供类型信息,它只是说编译器,"会很好的"。 所以通过省略它,你就不会做任何坏事。 在钻石操作符合法的任何地方,编译器都可以使用它。

恕我直言,有一个清晰的和简单的方法将一个源标记为java 7比发明这样的奇怪的事情会更有用。 这样标记的代码原始类型可以被禁止而不会丢失任何内容。

顺便说一下,我不认为它应该使用编译 switch 完成。 程序文件的Java版本是文件的属性,根本没有选项。 使用一些琐碎的东西


package 7 com.example;

可以让它清晰( 你可能喜欢一些更复杂的东西,包括一个或者多个复杂的关键字) 。 它甚至允许编译为不同的Java版本编写的源代码而没有任何问题。 它将允许引入新的关键字( e.g,"模块") 或者丢弃一些过时的特性( 单个文件中的多个非公共non-nested类) 而不会丢失任何兼容性。

当你写入时 List<String> list = new LinkedList(); 编译器生成一个"未选中"警告。 你可能会忽略它,但是如果你忽略这些警告,你可能会错过一个警告,通知你有关真实类型安全问题的警告。

所以,最好编写一个不产生额外警告的代码,diamond操作符允许你在方便的方式下进行,而无需不必要的重复。

diamond运算符的要点是在声明泛型类型时减少代码类型。 它对运行时没有任何影响。

如果你在 Java 5和 6中指定,


List<String> list = new ArrayList();

你必须指定 @SuppressWarnings("unchecked")list ( 否则,你将得到一个未经检查的强制转换警告) 。 我的理解是,钻石运营商试图让开发更加容易。 它在运行时执行泛型时没有任何作用。

所有的回应都是有效的,但用例并不是完全有效的。 如果一个查看 Guava 特别是集合相关的东西,已经完成了静态方法相同。 比如 Lists.newArrayList() 允许你写入


List<String> names = Lists.newArrayList();

或者使用静态导入


import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one","two","three");

Guava 还有其他非常强大的特性,我实际上想不出 <>的用处。

是更有用的,如果他们做了钻石运营商默认的行为,也就是说,从左边的类型是inferenced表达式的类型或者inferenced从左边右边。 后者是 Scala 中发生的事情。

...