Java Generics - 无法从<! - 转换?将MyObject - >扩展为<myobject> </myobject>

时间:2015-01-24 19:48:28

标签: java generics

为什么以下代码会出现编译错误?

public MyObject(Builder<? extends MyObject> builder) {
    // Type mismatch: cannot convert from MyObject.Builder<capture#5-of ? extends MyObject> to MyObject.Builder<MyObject>
    Builder<MyObject> myObjBuilder = builder;
}

如果Builder类型是MyObject的子类,那么为什么不能将构建器分配给MyObject?我需要这样做,因为我无法使用构建器的MyObject类型的对象。看一下这段代码,例如:

public MyObject(Builder<? extends MyObject> builder) {
    // The method getData(capture#8-of ? extends MyObject) in the type Builder<capture#8-of ? extends MyObject> is not applicable for the arguments (MyObject)
    this.data = builder.getData(this);
}

我觉得应该允许这样做。或者我在这里遗漏了什么?有没有办法在不将构建器强制转换为(Builder<MyObject>)并且必须使用@SuppressWarnings的情况下执行此操作?

另请注意,我需要构建器<? extends MyObject>,因为MyObject及其构建器将被子类化(因为它是抽象的)。

感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

因为Foo<? extends Bar>不是Foo<Bar>

Foo有一个方法:

void add (T t)

然后按合同,您只能添加T个对象。现在,如果将T实例化为? extends Bar,我们就不知道该类型。接受Bar可能会导致有问题的行为:如果您有ArrayList<Foo>,则期望ArrayList仅包含Foo个实例。如果您将ArrayList<Foo>视为ArrayList<SuperFoo>,则无法保证ArrayList<Foo>仅包含Foo

某些语言启用covariance:如果您只使用T作为输出,则可以说类Foo<T>也与Foo<SuperT>相同(相同)输入)。但目前Java并不支持这一点。然而,C#在接口级别上。