4 回答
TA贡献1772条经验 获得超6个赞
这个问题
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
s 的无参数构造函数!
TA贡献2065条经验 获得超14个赞
你的理解有点缺陷。钻石操作员是一个很好的功能,因为你不必重复自己。在声明类型时定义类型一次是有意义的,但在右侧再次定义它是没有意义的。DRY原则。
现在解释有关定义类型的所有模糊。你是正确的,在运行时删除了类型,但是一旦你想要从具有类型定义的List中检索某些内容,你就会将它作为你在声明列表时定义的类型返回,否则它会丢失所有特定的功能并且只有对象功能,除非您将检索到的对象强制转换为原始类型,这有时会非常棘手并导致ClassCastException。
使用List<String> list = new LinkedList()
将获得rawtype警告。
添加回答
举报