我在泛型方面存在一些问题。我有一个带有多个子类的BaseObject
以及一个带有与BaseContainer<T extends BaseObject>
子类对应的子类的BaseObject
。
public class TestClass extends BaseClass<BaseContainer<BaseObject>> {
// method signature tied to BaseClass generic
@Override
private BaseContainer<BaseObject> createContainer() {
BaseContainer<BaseObject> container;
// example logic here to determine which container to use
if (Math.random() < 0.5) {
container = new Parent1Container(); // incompatible types
} else {
container = new Parent2Container(); // incompatible types
}
return container;
}
abstract static class BaseObject {}
static class Parent1Object extends BaseObject {}
static class Parent2Object extends BaseObject {}
abstract static class BaseContainer<T extends BaseObject> {
public abstract void foo(T object);
}
static class Parent1Container extends BaseContainer<Parent1Object> {
public void foo(Parent1Object object) {}
}
static class Parent2Container extends BaseContainer<Parent2Object> {
public void foo(Parent2Object object) {}
}
}
public class BaseClass<T extends BaseContainer> {
public abstract T createContainer();
}
我有一个返回BaseContainer<BaseObject>
的方法。不幸的是,实例化BaseContainer
的子类会导致类型不兼容错误。
我已经尝试将强制转换添加到容器实例化中,但它留下了丑陋的未经检查的警告,这让我觉得我只是缺少某些东西。我想避免这些并禁止警告。
如果可能,我如何重新编写任何类以使createContainer()
方法有效?
答案 0 :(得分:1)
正如here所写,
List<Number>
和List<Integer>
都不是另一个的subtype
,即使Integer
是Number
的子类型。因此,任何以List<Number>
作为参数的方法都不接受List<Integer>
的参数。如果有,则可以在其中插入Number
Integer
,这违反了类型安全。
由于BaseClass
位于库中而您无法对其进行修改,因此无法正常处理此情况,即按预期进行处理。
答案 1 :(得分:1)
由于Parent1Container
和Parent2Container
不完全是BaseContainer<BaseObject>
,BaseContainer<? extends BaseObject>
你需要相应地改变签名:
public class TestClass extends BaseClass<BaseContainer<? extends BaseObject>> {
...
public BaseContainer<? extends BaseObject> createConstructor() {
if (Math.random() < 0.5) {
return new Parent1Container();
} else {
return new Parent2Container();
}
}
...
}
BaseContainer<BaseObject>
引用了所有能够“处理”任何BaseObject的BaseContainer(包括扩展类)实例,其中handle是它可以对该类型参数执行的所有操作的毯子术语。
相反,BaseContainer<? extends BaseObject>
指的是那些旨在处理顶级父类未知的所有BaseObject子集的BaseContainer实例(因此?
)。它?
碰巧是BaseObject,那么这两个集合就是等价的。
如果您的案例?
可以是Parent1Object
或Parent2Object
,那么您只能将其保留为?
。