Java泛型&amp;使用<s extends =“”{class} =“”>的不兼容类型

时间:2016-11-09 21:35:51

标签: java generics

abstract class AbsClass {}

class MyAbs extends AbsClass {}

class MyClass<S extends AbsClass> {
    S getObj() {
        return new MyAbs();
    }
}

获取编译器问题:

  

错误:(33,16)java:不兼容类型:MyAbs无法转换为S

这样做的正确方法是什么?

编辑: 我希望能够初始化MyClass {MyAbs},然后调用getObj(),它会返回一个MyAbs对象。在Andy的回答中,我必须将AbsClass转换为MyAbs或MySecondAbs,这是我试图避免的事情

3 个答案:

答案 0 :(得分:5)

Andy描述了如何解决问题,我将尝试解释原因。

S不能保证可分配给MyAbs,只能分配给AbsClass,每个实例都会指定AbsClass的子类。

考虑:

class MyOtherAbs extends AbsClass {}

MyClass myClass = new MyClass<MyOtherAbsClass>{};

这会与你所拥有的相冲突。

<强>更新

根据您的评论,您似乎希望实现上述目标。如果MyOtherAbs有一个带参数的构造函数,那么挑战是什么呢?或者实现为Singleton(即私有构造函数和静态getInstance())。简而言之,没有保证统一的方法可以构建这些。此外,由于类型擦除,在运行时,S的概念消失了,所以你不能做类似的事情:

return new S();

你基本上有两种选择,一种是使用子类:

public interface AbsClassFactory<S extends AbsClass>{ //takes the place of MyClass
    public S getInstance();
}

MyAbsFactory implements AbsClassFactory<MyAbs>{
    public MyAbs getInstance(){
        return new MyAbs(); //or however MyAbs is instantiated
    }
}

另一个选择是反思:

class MyClass {
    public <S extends AbsClass> S getObj(Class<S> clazz) throws InstantiationException, IllegalAccessException {
        return clazz.newInstance();
    }
}

请注意,第二个假设没有可用的arg构造函数,如果没有,则抛出运行时异常。

答案 1 :(得分:3)

S延伸MyAbs,而不是相反。任何S类型的对象都可以转换为MyAbs,但MyAbs不能转换为它的派生类。

请解释你想要达到的目标。

答案 2 :(得分:1)

您的评论似乎可以使用explain界面完成相同的操作:

Supplier