我有两个同构类型层次结构。第一个的基本类型是BaseA,第二个的基本类型是BaseB。我知道如何将BaseB的任何子类的任何对象转换为其对应的BaseA的子类型。我想实现一个方法,该方法采用BaseB类型的对象确定其类并构造BaseA对应子类型的对象。示例代码:
public interface BaseA...
public interface BaseB...
public class DerA implements BaseA...
public class DerB implements BaseB...
...
public interface Transform<A,B> {
A toA (B b);
}
public class DerAtoDerB implements Transform<DerA,DerB> {
DerA toA (DerB b){...}
}
public class Transformations {
private static Map<Class<?>, Transform<? extends BaseA, ? extends BaseB>> _map =
new HashMap<>();
static {
_map.put(DerB.class, new DerAtoDerB());
}
public static <B extends BaseB> BaseA transform(B b){
Transform<? extends BaseA, ? extends BaseB> t = _map.get(b.getClass());
return t.toA(b); // Compile error: Transform<A,B#2> cannot be applied to given types
}
为什么
<B extends BaseB>
与<? extends BaseB>
不兼容?另外,如果我尝试实现这样的静态转换方法:public static BaseA transform(BaseB b){
Transform<? extends BaseA, ? extends BaseB> t = _map.get(b.getClass());
return t.toA(b); // Compile error: Transform<A,B> cannot be applied to given types
}
我收到编译错误:
Transform<A,B> cannot be applied to given types
任何人都可以向我解释我在使用泛型药物时做错的事情吗?
最佳答案
问题在于,在transform
方法中,编译器无法得知类型参数B extends BaseB
和从映射中获取的Transform
类(? extends BaseB
)中的第二个类型参数实际上代表了BaseB
的相同子类。没有什么能阻止您在 map 中存储不兼容的类型:
_map.put(DerB.class, new AnotherDerAtoAnotherDerB()); // the types don't match
您是保证映射中的类型匹配的人,因此您需要通过将其强制转换为正确的类型来告知编译器:
@SuppressWarnings("unchecked")
public static <B extends BaseB> BaseA transform(B b) {
Transform<? extends BaseA, B> t =
(Transform<? extends BaseA, B>)_map.get(b.getClass());
return t.toA(b);
}