我有以下课程:
public interface ModelObject {
}
public interface Resource {
}
public interface Transformer <F,T>{
}
public interface WrapperFactory {
Transformer<Resource, Wrap<? extends ModelObject>> createMapper();
}
public class Wrap<E extends ModelObject> {
}
public class AbstractBaseTransformer<F,T> implements Transformer<F,T> {
}
public class ConcreteModel implements ModelObject {
}
public class ConcreteTransformer extends AbstractBaseTransformer<Resource, Wrap<ConcreteModel>> {
}
public class ConcreteFactory implements WrapperFactory {
@Override
public Transformer<Resource, Wrap<? extends ModelObject>> createMapper() {
return new ConcreteTransformer();
}
}
ConcreteFactory没有编译声明ConcreteTransformer与返回的
不兼容Transformer<Resource, Wrap<? extends ModelObject>>
我看不出这里有什么问题。 ConcreteTransformer将第一个参数绑定到Resource(与预期相同),同时将第二个参数绑定到:
Wrap<ConcreteModel>
应绑定到:
Wrap<? extends ModelObject>
当ConcreteModel实现它。
答案 0 :(得分:4)
这是一个更简单的版本,以缩小问题范围:
interface ModelObject {}
class ConcreteModel implements ModelObject {}
class Wrap<E extends ModelObject> {}
class SomeGeneric<T> {}
class Simple {
public SomeGeneric<Wrap<? extends ModelObject>> m() {
return new SomeGeneric<Wrap<ConcreteModel>>();
}
}
也不编译。
您的问题是SomeGeneric<Wrap<ConcreteModel>>
is not a SomeGeneric<Wrap<? extends ModelObject>>
。
答案 1 :(得分:1)
Wrap<ConcreteModel>
是Wrap<? extends ModelObject>
的子类型?是。
Transformer<Resource, Wrap<ConcreteModel>>
是Transformer<Resource, Wrap<? extends ModelObject>>
的子类型?否。
它与:
相同 String
是Object
的子类型?是。
List<String>
是List<Object>
的子类型?否。
基本上,要使参数化类型兼容,如果顶级参数不是通配符,则参数必须与完全匹配。在您的情况下,顶级参数不是通配符,并且参数不完全匹配。
你可能想要的是
Transformer<Resource, ? extends Wrap<? extends ModelObject>>
答案 2 :(得分:0)
可以将Wrap<ConcreteModel>
分配给Wrap<? extends ModelObject>
类型的变量。但这里的问题更复杂。
假设您有ArrayList<Wrap<? extends ModelObject>> list
。当您有这样的类型时,这意味着您可以在列表中添加Wrap<ConcreteModel>
,但这也意味着您可以向其添加Wrap<ModelObject>
。简而言之,这意味着您有一个列表,其中可以包含任何可以转换为ModelObject
的Wrap。
另一方面,拥有ArrayList<Wrap<ConcreteModel>> list
意味着您只能添加Wrap<ConcreteModel>
,而Wrap<ModelObject>
无法添加到其中,因为该列表只能包含ConcreteModel
{1}} s,被包裹的ModelObject
不是被包裹的ConcreteModel
,也不能被归为一个。
这正是你的情况。您声明了createMapper()
方法返回Transformer<Resource, Wrap<? extends ModelObject>>
。这意味着返回的Transformer的第二个参数必须能够是ModelObject
的任何子类,包括ModelObject
本身。相反,您正在尝试返回Transformer<Resource, Wrap<ConcreteModel>>
。
编译器需要强制执行此操作,因为Transformer<F, T>
可以声明一个方法:
void myMethod(F fObject, T tObject);
如果是这种情况,类型为myMethod
的对象的方法Transformer<Resource, Wrap<? extends ModelObject>>
将接受类型为ModelObject
的对象作为其第二个参数。另一方面,类型为Transformer<Resource, Wrap<ConcreteModel>>
的对象中的同一方法不能接受ModelObject
作为其第二个参数。