为什么我可以有一个方法接收带有通配符的列表:
public processGenerics(List<? extends User> users){...}但我不能以类似的方式实例化相同的列表?
List<? extends User> alist = new ArrayList<? extends User>();[编辑,而不是原始问题的一部分,但相关]为什么我不能以正常继承的相同方式执行与集合的投射:
List<User> users = new ArrayList<Admin>();Why can I have a method receiving a list with wildcards:
public processGenerics(List<? extends User> users){...}but I cannot instantiate that same List in a similar way?
List<? extends User> alist = new ArrayList<? extends User>();[Edited, not part of the original question, but relevant] Why can't I do casting with Collections the same way of normal inheritance:
List<User> users = new ArrayList<Admin>();最满意答案
你的问题最令人困惑的方面是你必须经历的泛型类型与经典原始类型的底层心理切换。
在泛型之前,每个变量都有一个明确的类型,比如Object。 虽然你可以给它分配一个字符串,但字符串仍然是一个对象,所以这个范例保留 - 在所有情况下,你都将一个对象分配给一个对象var。
泛型不适用。 你可能有一个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,因为它已经被很好地覆盖了。
The most confusing aspect of your problem is the underlying mental switch you must undergo with generic types vs. classic raw types.
Before Generics, each variable had a definite type, such as Object. Although you could assign a String into it, a String still is an Object, so the paradigm holds—in all cases you are assigning something that is an Object into an Object var.
Not so with Generics. You may have a List<? extends Number>, which can be assigned from a range of types that have no instanceof relation to the declared variable type, but only satisfy a certain pattern. The pattern is described by the wildcard.
So, to make your life easier when you reason about generic variable types, you need to abandon the simple and cozy notion of a definite type and think in terms of these "type patterns".
As far as the second part of your question: List<User> and List<Admin> are completely unrelated types, regardless of the fact that User and Admin are related. That's how Generics work, and there's a good reason for it. Java cannot allow you to add OrdinaryUser to a List<Admin>, and under your assumption that could happen:
List<User> users = new ArrayList<Admin>(); users.add(new OrdinaryUser()); // shouldn't be allowed!The official term is that generic types are invariant with respect to their type parameter. It is best to google around for this term as it is already very well covered.
更多推荐
发布评论