简体   繁体   English

如何推断通用类型以避免未经检查的转换

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM