我有两个类实现接口
public class MyClassA implements IClassA {
// code
}
public class MyClassB implements IClassB {
// code
}
我有转换这些类的实用程序功能
public class Util {
public static List<MyClassB> convertAtoB(List<MyClassA> aClasses) {
// logic
}
}
最后,我有一个通用类
public class GenericClass <D extends IClassA, V extends IClassB> {
public List<V> someFunc(List<D> in) {
return Util.convertAtoB(in); // ERROR HERE
}
}
错误是
Required Type: List<MyClassA>
Provided: List<D>
出了什么问题
编辑
以下是我想要实现的
我有许多转换器函数,它们使用一些逻辑将一种类型的列表转换为另一种类型。函数如下所示,在Util类中
List<B> convertAtoB(List<A> list) { }
List<C> convertBtoC(List<B> list) { }
List<D> convertCtoD(List<C> list) { }
List<E> convertDtoE(List<D> list) { }
... so on
现在,所有这些都必须异步调用。因此,我将使用AyncTask来实现此目的。现在我有两个选择:
选项1:创建多个类,每个类扩展AsyncTask并在每个类中调用相应的转换器函数。
class ConvertAtoBAsync extends AsyncTask<List<MyClassA>, Void, List<MyClassB>> {
public List<MyClassB> doInBackground(List<MyClassA> ...lists) {
return convertAtoB(lists[0]);
}
}
class ConvertBtoCAsync extends AsyncTask<List<MyClassB>, Void, List<MyClassC>> {
public List<MyClassC> doInBackground(List<MyClassB> ...lists) {
return convertBtoC(lists[0]);
}
}
.. so on
选项2:创建一个通用的AsyncTask类,该类可以基于类类型调用特定类型的转换器
public class ConvertAsync <D extends IClassIn, V extends IClassOut> {
ConvertAsync(Class _class) { mClass = _class }
public List<V> someFunc(List<D> in) {
if(mClass = MyClassA.class)
return Util.convertAtoB(in); // ERROR HERE
else if(mClass = MyClassB.class)
return Util.convertBtoC(in); // ERROR HERE
.. so on
}
}
我可以不使用选项2吗
对于Java Generics,在需要List<MyClassA>
的情况下,必须提供与该元素类型完全相同的List
,例如ArrayList<MyClassA>
,而不是ArrayList<MySubClassA>
。
此外,在Util
中,您需要参数为List<MyClassA>
,而不是使用接口IClassA
。
因此,当您试图将List<D>
传递给Util
方法时,编译器会拒绝,原因有两个:
- 该方法需要
MyClassA
元素,而List<D>
只能保证接口类型为IClassA
的元素,这些元素可能来自不同的MyOtherClassA
- 即使没有这种差异,需要
List<IClassA>
的方法也不会接受List<MyClassA>
,即使MyClassA
实现了IClassA
(基本原理见下文(
因此您应该更改Util
方法以接受List<? extends IClassA>
。
基本原理
在方法内部,您可能会尝试将某些内容存储到该列表中。该方法看到一种类型的List<IClassA>
,因此存储一个MyOtherClassA
实例看起来完全可以。但实际上您传入了一个List<MyClassA>
,现在这个列表被一个不属于MyClassA
类型的元素损坏了。因此,Java被设计为不允许这样做,编译器将其标记为错误情况是正确的。
通过声明List<? extends IClassA>
,可以使用List<MyClassA>
作为实际参数,同时有效地禁止在方法内部存储到该列表中。
编辑:
你为你的问题添加了更多的上下文。不过,我的建议是修改Util
方法以接受List<? extends IClassA>
和类似的方法。这将是使方案2发挥作用的主要因素。