繁体   English   中英

Java Generics&Collections,为什么不能使用通配符实例化新的List?

[英]Java Generics & Collections, why can't I instantiate new List with wildcards?

为什么我有一种方法可以接收带有通配符的列表:

public processGenerics(List<? extends User> users){...}

但是我无法以类似方式实例化相同的List?

List<? extends User> alist = new ArrayList<? extends User>();

[已编辑,不是原始问题的一部分,而是相关的]为什么我不能对Collections进行强制继承的相同方法:

List<User> users = new ArrayList<Admin>();

您无法实例化通配符实例。 您只能实例化特定实例,例如:

List<? extends User> alist1 = new ArrayList<User>();
List<? extends User> alist2 = new ArrayList<SubClassOfUser>();

什么List<? extends User> List<? extends User>装置“A列表,其类型为在编译时未知的,但其具有上界的User -要么是User或子类User

虽然变量可以用通配符定义,但实例可能不可以-它必须是某物的列表

问题中最令人困惑的方面是泛型类型与经典原始类型之间必须进行的基本精神转换。

在泛型之前,每个变量都有一个确定的类型,例如Object。 尽管您可以向其中分配一个字符串,但字符串仍然是一个对象,因此该范例适用—在所有情况下,您都是将某个对象作为对象分配给对象变量。

泛型则不是这样。 您可能有一个List<? extends Number> List<? extends Number> ,可以从与instanceof的变量类型不相关但仅满足特定模式的一系列类型中分配。 该模式由通配符描述。

因此,为了使您在泛型变量类型推理时的工作变得更加轻松,您需要放弃确定类型的简单而舒适的概念,并根据这些“类型模式”进行思考。

至于问题的第二部分: List<User>List<Admin>是完全不相关的类型,无论UserAdmin是否相关。 这就是泛型的工作方式,这有充分的理由。 Java不允许您将OrdinaryUser添加到List<Admin> ,并且在您的假设下可能会发生:

List<User> users = new ArrayList<Admin>();
users.add(new OrdinaryUser()); // shouldn't be allowed!

官方术语是泛型类型相对于其类型参数是不变的 这个词最好用Google搜索,因为它已经被很好地涵盖了。

构造:

List<? extends User> user

表示可以保存List<T>实例的变量,其中T是用户的某些未知子类型。 当您实际实例化ArrayList<T>时,您总是知道它应该保存什么类型,因此让您在那里表达这种不确定性没有用。

换一种说法:变量可以保存(潜在地)许多不同类型的对象。 对象实例只有其自己的一种类型。 这就是变量声明必须更加灵活的原因。

new运算符通过为新对象分配内存并返回对该内存的引用来实例化一个类。 甲骨文

使用通配符创建对象时,您不知道要分配多少内存。

作为参数类型传递给方法的内容不涉及内存分配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM