[英]How to infer the generic type to avoid unchecked casting
Suppose we have a class A that has two subclasses A1, A2. 假设我们有一个具有两个子类A1,A2的类A。 Suppose we have another class B, that also has two subclasses, B1 an B2: 假设我们还有另一个类B,它也有两个子类B1和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: 现在,如果我们有这样的C1类:
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? 如何实现B类的getMyGenericList,以便避免未经检查的转换警告?
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>
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. 使用当前定义B
类的方式, myGenericList
实例变量可以保存A的任何子类型的List,因此,当转换为List<A1>
时获得未经检查的强制转换警告是合理的。 It could be a List<A>
or a List<A2>
. 它可以是List<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>
如果您不太在意列表中的哪个A
,则可以将其分配给List<? extends 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. 但是,如果您真的想从B1
返回List<A1>
,那么B
类的泛型就是您的答案。 Define T
at the class level with an upper bound of A
. 在类级别定义T
,上限为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. B
子类将分别定义T
是什么。
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
: 现在,使用具体参数A1
定义了子类:
class B1 extends B<A1>{
B1(List<A1> a1List){
super(a1List);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.