java 7中的菱形运算符允许以下代码:
列表<;字符串>;列表=新建链接列表<&燃气轮机;();
但是,在Java 5/6中,我可以简单地编写:
列表<;字符串>;列表=新的LinkedList();
我对类型擦除的理解是,它们完全相同。(无论如何,泛型将在运行时被删除)
为什么要为钻石而烦恼呢?它允许哪些新功能/类型的安全性?如果它不能产生任何新的功能,为什么他们会把它作为一个特性来提呢?我对这个概念的理解有缺陷吗
问题在于
列表<;字符串>;列表=新的LinkedList();
在左边,您使用的是通用类型列表<;字符串>在右侧,您使用的是原始类型链接列表。Java中的原始类型实际上只是为了与泛型之前的代码兼容而存在的,除非
你绝对必须这么做
现在,如果Java从一开始就有泛型,而没有在有泛型之前创建的类型,例如LinkedList,那么它可能已经创建了泛型,以便泛型类型的构造函数在可能的情况下从赋值的左侧自动推断其类型参数。但事实并非如此,为了向后兼容,它必须以不同的方式对待原始类型和泛型类型。这使得他们需要使用一种稍微不同但同样方便的方法来声明泛型对象的新实例,而不必重复其类型参数。。。钻石操作员
就您最初的List<;字符串>;list=new LinkedList(),编译器会为该赋值生成警告,因为它必须。考虑这一点:
列表<;字符串>;字符串=…//包含一些字符串的列表
//完全合法,因为您使用了原始类型并丢失了所有类型检查!
列表<;整数>;整数=新链接列表(字符串);
泛型的存在是为了提供编译时保护,防止做错误的事情。在上面的示例中,使用raw类型意味着您无法获得此保护,并且在运行时会出现错误。这就是为什么不应该使用原始类型
//不合法,因为右侧实际上是通用的!
列表<;整数>;整数=新链接列表<&燃气轮机;(字符串);
但是,菱形运算符允许将赋值的右侧定义为具有与左侧相同类型参数的真正泛型实例。。。无需再次键入这些参数。它允许您保持泛型的安全性,与使用原始类型几乎相同
我认为需要理解的关键是,原始类型(没有<;)不能被视为泛型类型。当您声明一个原始类型时,您不会得到泛型的任何好处和类型检查。您还必须记住,泛型是Java语言的通用部分。。。它们不仅仅适用于Collections的无参数构造函数