为什么我有一种方法可以接收带有通配符的列表:
public processGenerics(List<? extends User> users){...}
但是我无法以类似方式实例化相同的List?
List<? extends User> alist = new ArrayList<? extends User>();
[已编辑,不是原始问题的一部分,而是相关的]为什么我不能以正常继承的相同方式对Collections进行强制转换:
List<User> users = new ArrayList<Admin>();
最佳答案
问题中最令人困惑的方面是泛型类型与经典原始类型之间必须进行的基本精神转换。
在泛型之前,每个变量都有一个确定的类型,例如Object。尽管您可以在其中分配一个字符串,但仍然是String的是对象,因此,该范例适用—在所有情况下,您都将是Object 的对象分配给Object var。
泛型则不是这样。您可能有一个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!
官方术语是泛型类型相对于其类型参数而言是不变的。最好搜索一下这个词,因为它已经被很好地涵盖了。