Suppose we have a class A that has two subclasses A1, A2. Suppose we have another class B, that also has two subclasses, B1 an B2:
class B{
List<? extends A> myGenericList;
B(List<? extends A> myGenericList){
this.myGenericList = myGenericList;
}
public List<? extends A> getMyGenericList(){
return myGenericList;
}
}
class B1 extends B{
B1(List<A1> a1List){
super(a1List);
}
}
class B2 extends B{
B2(List<A2> a2List){
super(a2List);
}
}
Now, if we have a class C1 like this:
class C1{
...
public void doSomethingWithB1(B1 b1){
List<A1> a1list = (List<A1>)b1.getMyGenericList();
}
...
}
How can I implement getMyGenericList of class B so I can avoid the unchecked casting warning?
I tried something like this:
public <T extends A> List<T> getMyGenericList() {
return this.myGenericList;
}
but the compiler complains with cannot convert from List<capture#3-of ? extends A> to List<T>
cannot convert from List<capture#3-of ? extends A> to List<T>
Is there any way to do it?
Thanks in advance.
With the current way you've defined the B
class, the myGenericList
instance variable could hold a List of any subtype of A, so the unchecked cast warning you get when casting to List<A1>
is justified. It could be a List<A>
or a List<A2>
.
If you don't really care which A
you get in the list back, you can just assign it to a List<? extends A>
List<? extends A>
.
List<? extends A> a1list = b1.getMyGenericList();
But if you really want to get a List<A1>
back from a B1
, then generics on the B
class is your answer. Define T
at the class level with an upper bound of A
. Use it throughout your class to replace your wildcards.
class B<T extends A>
{
List<T> myGenericList;
B(List<T> myGenericList){
this.myGenericList = myGenericList;
}
public List<T> getMyGenericList(){
return myGenericList;
}
}
Your subclasses of B
will define what T
is respectively.
class B1 extends B<A1> // rest of class is the same
class B2 extends B<A2> // rest of class is the same
This way you have eliminated the unchecked cast warning and even the need to cast at all.
List<A1> a1list = b1.getMyGenericList();
You should move your generic definition to class level as following:
class B<T extends A> {
List<T> myGenericList;
B(List<T> myGenericList){
this.myGenericList = myGenericList;
}
public List<T> getMyGenericList(){
return myGenericList;
}
}
Now the subclass is defined with concrete parameter A1
:
class B1 extends B<A1>{
B1(List<A1> a1List){
super(a1List);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.