Java 7中菱形运算符(<;>;)的作用是什么?

Java 7中菱形运算符(<;>;)的作用是什么?,java,generics,java-7,diamond-operator,Java,Generics,Java 7,Diamond Operator,java 7中的菱形运算符允许以下代码: List<String> list = new LinkedList<>(); List List=newlinkedlist(); 但是,在Java 5/6中,我可以简单地编写: List<String> list = new LinkedList(); List List=newlinkedlist(); 我对类型擦除的理解是,它们完全相同。(无论如何,泛型将在运行时被删除) 为什么要为钻石而烦恼呢?它允许

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

List<String> list = new LinkedList<>();
List List=newlinkedlist();
但是,在Java 5/6中,我可以简单地编写:

List<String> list = new LinkedList();
List List=newlinkedlist();
我对类型擦除的理解是,它们完全相同。(无论如何,泛型将在运行时被删除)


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

这一行会导致[unchecked]警告:

List<String> list = new LinkedList();
List List=newlinkedlist();
因此,问题变了:为什么只有在创建新集合的情况下,[unchecked]警告才会被自动抑制

我认为,添加
功能比添加
功能要困难得多


UPD:我还认为,如果“仅为几件事”使用原始类型是合法的,那将是一场混乱。

你的理解有点错误。菱形操作符是一个很好的功能,因为您不必重复自己的操作。在声明类型时定义一次类型是有意义的,但在右侧再次定义它是没有意义的。干燥原理

现在来解释所有关于定义类型的模糊。在运行时删除该类型是正确的,但一旦您希望从具有类型定义的列表中检索某个对象,则可以将其恢复为声明列表时定义的类型,否则它将丢失所有特定功能,并且仅具有对象功能,但将检索到的对象强制转换为其原始类型时除外,该类型可以有时会非常棘手,并导致ClassCastException

使用
List List=new LinkedList()
将得到rawtype警告。

当您编写
List List=new LinkedList()时,编译器生成“未检查”警告。您可以忽略它,但如果您过去忽略这些警告,您也可能会错过通知您实际类型安全问题的警告


因此,最好编写不产生额外警告的代码,而diamond运算符允许您以方便的方式执行此操作,而无需不必要的重复。

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

如果在Java5和Java6中指定

List<String> list = new ArrayList();
List List=new ArrayList();
您必须在
列表中指定
@SuppressWarnings(“未选中”)
(否则您将得到未选中的强制转换警告)。我的理解是,钻石运营商正在努力使开发更容易。它与泛型的运行时执行毫无关系。

的问题

List<String> list = new LinkedList();
泛型的存在是为了提供编译时保护,防止做错误的事情。在上面的示例中,使用raw类型意味着您无法获得此保护,并且在运行时会出现错误。这就是为什么不应该使用原始类型

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
//不合法,因为右侧实际上是通用的!
列表整数=新链接列表(字符串);
但是,菱形运算符允许将赋值的右侧定义为具有与左侧相同类型参数的真正泛型实例。。。无需再次键入这些参数。它允许您使用与使用原始类型几乎相同的努力来保持泛型的安全性


我认为需要理解的关键是,原始类型(没有
)不能与泛型类型一样对待。当您声明一个原始类型时,您不会得到泛型的任何好处和类型检查。您还必须记住,泛型是Java语言的通用部分。。。它们不仅仅适用于
Collection
s的无参数构造函数

理论上,菱形运算符允许您通过保存重复的类型参数来编写更紧凑(可读)的代码。实际上,这只是两个让人困惑的角色,没有给你任何东西。为什么?

  • 没有一个理智的程序员在新代码中使用原始类型。因此,编译器可以简单地假设,通过不编写类型参数,您希望它推断出它们
  • 菱形操作符不提供类型信息,它只是告诉编译器“没事”。因此,省略它不会造成伤害。在钻石运算符合法的任何地方,编译器都可以“推断”钻石运算符
  • IMHO说,有一种清晰简单的方法将源代码标记为Java7比发明这样奇怪的东西更有用。在这样标记的代码中,可以在不丢失任何内容的情况下禁止原始类型

    顺便说一句,我不认为应该使用编译开关来完成。程序文件的Java版本是文件的一个属性,没有任何选项。使用像这样琐碎的东西

    package 7 com.example;
    

    可以说清楚(你可能更喜欢一些更复杂的东西,包括一个或多个花哨的关键字)。它甚至允许编译为不同Java版本编写的源代码,而不会出现任何问题。它将允许引入新的关键字(例如,“模块”)或删除一些过时的功能(单个文件中的多个非公共非嵌套类或任何内容),而不会失去任何兼容性。

    其他响应中所述的所有内容都是有效的,但用例并非完全有效。如果一个人签出了,特别是与集合相关的东西,静态方法也是如此。例如,它允许你写作

    List<String> names = Lists.newArrayList();
    
    List name=Lists.newArrayList();
    
    或者使用静态导入

    import static com.google.common.collect.Lists.*;
    ...
    List<String> names = newArrayList();
    List<String> names = newArrayList("one", "two", "three");
    
    导入静态com.google.common.collect.Lists.*;
    ...
    列表名称=newArrayList();
    列表名称=newArrayList(“一”、“二”、“三”);
    
    番石榴还有其他非常强大的功能,像这样,我实在想不出它有什么用途

    如果他们将菱形操作符行为设置为默认值,也就是说,类型为inf,则会更有用
    import static com.google.common.collect.Lists.*;
    ...
    List<String> names = newArrayList();
    List<String> names = newArrayList("one", "two", "three");