[英]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>
是完全不相关的类型,无论User
和Admin
是否相关。 这就是泛型的工作方式,这有充分的理由。 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>
时,您总是知道它应该保存什么类型,因此让您在那里表达这种不确定性没有用。
换一种说法:变量可以保存(潜在地)许多不同类型的对象。 对象实例只有其自己的一种类型。 这就是变量声明必须更加灵活的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.