4

我有以下课程:

    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 实现的那样。

4

3 回答 3

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>>();
    }
}

也不编译。

你的问题是 aSomeGeneric<Wrap<ConcreteModel>>不是 aSomeGeneric<Wrap<? extends ModelObject>>

于 2013-08-16T22:38:21.327 回答
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>>

于 2013-08-19T06:27:00.713 回答
0

AWrap<ConcreteModel>可以分配给类型为 的变量Wrap<? extends ModelObject>。但这里的问题更复杂。

假设你有一个ArrayList<Wrap<? extends ModelObject>> list. 当你有这样一个类型时,意味着你可以Wrap<ConcreteModel>在列表中添加一个,但也意味着你可以Wrap<ModelObject>向它添加一个。简而言之,这意味着您有一个列表,其中可以包含任何可以转换为ModelObject.

另一方面,拥有 aArrayList<Wrap<ConcreteModel>> list意味着您只能向其添加Wrap<ConcreteModel>s,而Wrap<ModelObject>不能向其添加 a,因为列表只能包含 Wrapped ConcreteModels,而 WrappedModelObject不是 WrappedConcreteModel也不能强制转换为一个。

这正是你的情况。你声明你的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>> 不能接受 aModelObject作为其第二个参数。

于 2013-08-16T23:27:03.207 回答