java 7中的diamond操作符允许如下代码:
List<String> list = new LinkedList<>();
然而在Java 5/6中,我可以简单地写:
List<String> list = new LinkedList();
我对类型擦除的理解是它们是完全相同的。(无论如何泛型都会在运行时被删除)。
为什么要为钻石费心呢?它允许哪些新的功能/类型安全?如果它没有产生任何新的功能,他们为什么要把它作为一个特性来提及呢?我对这个概念的理解有缺陷吗?
java 7中的diamond操作符允许如下代码:
List<String> list = new LinkedList<>();
然而在Java 5/6中,我可以简单地写:
List<String> list = new LinkedList();
我对类型擦除的理解是它们是完全相同的。(无论如何泛型都会在运行时被删除)。
为什么要为钻石费心呢?它允许哪些新的功能/类型安全?如果它没有产生任何新的功能,他们为什么要把它作为一个特性来提及呢?我对这个概念的理解有缺陷吗?
当前回答
当你写List<String> List = new LinkedList();,编译器产生一个“unchecked”警告。您可以忽略它,但是如果您习惯了忽略这些警告,那么您也可能会错过通知您实际类型安全问题的警告。
所以,最好写一段不产生额外警告的代码,菱形运算符可以让你以一种方便的方式做到这一点,而没有不必要的重复。
其他回答
菱形操作符的作用仅仅是在声明泛型类型时减少代码的类型。它对运行时没有任何影响。
如果在Java 5和Java 6中指定,唯一的区别是,
List<String> list = new ArrayList();
你必须指定@SuppressWarnings("unchecked")到列表中(否则你将得到一个未检查的强制转换警告)。我的理解是,diamond operator正试图让开发变得更容易。它与泛型的运行时执行完全没有关系。
理论上,菱形操作符可以通过保存重复的类型参数来编写更紧凑(且可读)的代码。实际上,这只是两个令人困惑的字符,什么都没有。为什么?
理智的程序员不会在新代码中使用原始类型。因此,编译器可以简单地假设不写类型参数就可以推断它们。 菱形操作符不提供类型信息,它只是告诉编译器,“它会没事的”。所以省略它也无妨。在菱形操作符合法的任何地方,编译器都可以“推断”它。
在我看来,有一种清晰而简单的方法将源代码标记为Java 7将比发明这些奇怪的东西更有用。在这样标记的代码中,原始类型可以被禁止而不会损失任何东西。
顺便说一句。但是,我认为不应该使用编译开关。程序文件的Java版本是文件的一个属性,根本没有选项。使用像这样微不足道的东西
package 7 com.example;
你可能更喜欢一些更复杂的东西,包括一个或多个花哨的关键字。它甚至允许将为不同Java版本编写的源代码一起编译,而不会出现任何问题。它将允许引入新的关键字(例如,“module”)或删除一些过时的特性(单个文件中多个非公共非嵌套类或其他)而不失去任何兼容性。
这一行导致[unchecked]警告:
List<String> list = new LinkedList();
因此,问题转换为:为什么[unchecked]警告仅在创建新集合时才自动抑制?
我认为,这比添加<>特性要困难得多。
UPD:我还认为,如果只在少数方面合法地使用原始类型,将会造成混乱。
当你写List<String> List = new LinkedList();,编译器产生一个“unchecked”警告。您可以忽略它,但是如果您习惯了忽略这些警告,那么您也可能会错过通知您实际类型安全问题的警告。
所以,最好写一段不产生额外警告的代码,菱形运算符可以让你以一种方便的方式做到这一点,而没有不必要的重复。
其他回答中的所有回答都是有效的,但用例并不完全有效。如果你检查了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还有其他非常强大的特性,实际上我想不出<>有什么用处。
如果他们将菱形操作符行为作为默认值,也就是说,从表达式的左侧推断类型,或者从右侧推断左侧的类型,这将会更有用。后者是在Scala中发生的事情。