[英]Java Generics — Assigning a list of subclass to a list of superclass
I have a basic question regarding assignment of a list of subclass to a list of superclass.我有一个关于将子类列表分配给超类列表的基本问题。
So I have something like the following:所以我有以下内容:
Class B extends A;
List <B> bList = new ArrayList<B>();
List <A> aList = bList;
Why does this last assignment fail?为什么最后一次分配失败? Sorry for the newbie question
对不起新手问题
When you declare a List of items of type A, only items of type A can be added or removed from the List.当您声明 A 类型的项目列表时,只能从列表中添加或删除类型 A 的项目。 If you need to include subclasses of A, use the generic wildcard
? extends A
如果需要包含 A 的子类,请使用通用通配符
? extends A
? extends A
to indicate so. ? extends A
来表示。 Your code should therefore be:因此,您的代码应为:
List <? extends A> aList = bList;
To explain this, let me substitute "B" with Integer and "A" with Number.为了解释这一点,让我用 Integer 代替“B”,用数字代替“A”。 This is just to make it a little easier to explain.
这只是为了使它更容易解释。
Class Integer extends Number;
List <Integer> iList = new ArrayList<Integer>();
List <Number> nList = iList // will fail
The reason this would fail is because nList can take any Number -- it can take Integer, it can take Double, or for that matter any subclass of Number.这将失败的原因是因为 nList 可以采用任何数字——它可以采用 Integer,它可以采用 Double,或者就此而言,它可以采用 Number 的任何子类。 However, this is not true for iList.
但是,对于 iList 来说,情况并非如此。 You cannot add a Double to iList because it accepts only Integer and its subclasses.
您不能将 Double 添加到 iList,因为它只接受 Integer 及其子类。 Hope this helps explain it to you.
希望这有助于向您解释。
List<B>
is not List<A>
: List<B>
不是List<A>
:
Through example: let say you have class B1 extends A{}
and class B2 extends A{}
then (if you would be able to do that:通过示例:假设您有
class B1 extends A{}
和class B2 extends A{}
然后(如果您能够这样做:
List<B1> b1 = new AList<B1>();
List<A> a = b1;
List<B2> b2 = new AList<B2>();
by the hypothesis, you should be able to do a.add(new B2()) but this is wrong.根据假设,您应该能够执行 a.add(new B2()) 但这是错误的。
If you try the same thing but using arrays
instead of lists, it will compile and throw exception in runtime.如果您尝试相同的操作但使用
arrays
而不是列表,它将在运行时编译并抛出异常。
We say that arrays are covariant and generics are invariant .我们说 arrays 是协变的,而 generics 是不变的。
to make the code compile you have the wite it:让代码编译你有它的智慧:
List<? extends A> a = b;
this says that a is a list of some subtype of A. _But you don know which one.这表示 a 是 A 的某个子类型的列表。_但你不知道是哪一个。 Because of that you can't do
a.put(X)
因此你不能做
a.put(X)
List<B>
and List<A>
are invariant
type. List<B>
和List<A>
是invariant
类型。 What you need is covariant
type.你需要的是
covariant
类型。 In this case, it is List<? extends A>
在这种情况下,它是
List<? extends A>
List<? extends A>
. List<? extends A>
。
Because generics are strict type safe .因为 generics 是严格类型安全的。
You can have你可以有
List<? extends A> aList = bList;
It says aList
can hold list of any type which is an A
它说
aList
可以保存任何类型的列表,它是A
Because List<B>
does not extend List<A>
.因为
List<B>
不扩展List<A>
。 For example, Integer
extends Number
and so does Long
.例如,
Integer
扩展Number
, Long
也是如此。 So List<Number>
can contain both Integer
and Long
.所以
List<Number>
可以同时包含Integer
和Long
。 So if you assign List<Integer>
to List<Number>
you will be able to add Long
to your list of integers.因此,如果您将
List<Integer>
分配给List<Number>
,您将能够将Long
添加到您的整数列表中。
You can declare你可以声明
List<? super B> superB;
And that would allow assignment to superB of any list that contains B and its super classes.这将允许将包含 B 及其超类的任何列表分配给 superB。 But it's not the same as in your case
aList=bList
.但这与您的情况不同
aList=bList
。
or或者
List<? extends A> extendsA;
Examples例子
List<? super Integer> superA;
superA = new ArrayList<Number>();
List<? extends Number> extendsNumber;
extendsNumber = new ArrayList<Integer>();
While at first glance you might think that乍一看,您可能会认为
Class B extends A;
List <B> bList = new ArrayList<B>();
List <A> aList = bList;
should work, the problem is obvious when you imagine actually using these lists:应该可以工作,当您想象实际使用这些列表时,问题就很明显了:
A something = new A();
aList.add( something ); // Should work because aList is a list of A's
but aList
was assigned to bList
, so that should be the same as但是
aList
已分配给bList
,因此应该与
bList.add( something ); // Here's the problem
bList.add()
takes a B
, but something
is an A
, and an A
is not a B
! bList.add()
接受B
,但something
是A
,而A
不是B
!
And that's why generics should be (and are) strict type safe.这就是为什么 generics 应该(并且是)严格类型安全的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.