繁体   English   中英

如何返回参数化返回类型的子类,其参数类型是返回类型的参数类型的子类?

[英]How to return a subclass of parameterized return type whose parametric type is a subclass of the return type's parametric type?

标题听起来有点复杂,但事实上问题很简单。 我有以下方法:

AbstractClassA<AbstractClassB> myMethod() {...}

我想像这样调用它:

ClassAImpl<ClassBImpl> result = myMethod();

问题是,无论我尝试什么,我最终都得到了未经检查的强制警告或编译器错误。

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

这完全取决于。 最简单的答案是,您只需要将myMethod的结果转换为与结果相同的类型。 假设我们从问题中取出所有泛型,如下所示:

public class Demo {

    private abstract class AbstractClassA {}
    private class ClassAImpl extends AbstractClassA {}
    private abstract class AbstractClassB {}
    private class ClassBImpl extends AbstractClassB {}

    Demo() {
        ClassAImpl result = myMethod();
    }
    public AbstractClassA myMethod() {
        return new ClassAImpl();
    }
    public static void main(String[] args) {
        new Demo();
    }
}

myMethod的调用仍然是编译器错误,因为类型不匹配。 考虑这一点的一个好方法是想象你对myMethod体内的代码一无所知。 你怎么知道它返回ClassAImpl而不是AbstractClassA其他子类型? 所以为了使它工作,你需要像这样调用myMethod

ClassAImpl result = (ClassAImpl)myMethod()

至于泛型位,您可能希望您的方法签名类似于:

public AbstractClassA<? extends AbstractClassB> myMethod()

但也许想要这样的东西:

public AbstractClassA<ClassBImpl> myMethod()

甚至:

public ClassAImpl<ClassBImpl> myMethod()

除了最后一个之外的所有都需要一些显式的铸造。

为什么你到底会这样做呢? 你的设计是错误的,或者你遗漏了一些重要的信息。 如果myMethod与尝试调用位于同一个类中,那么调用者可以了解有关如何实现该方法的信息,则应创建一个返回更具体类型的私有myMethodAux 但是,您可能仍会遇到方差问题,因为ClassAImpl<ClassBImpl>不是AbstractClassA<AbstractClassB>的子类。 它是AbstractClassA<? extends AbstractClassB>的子类AbstractClassA<? extends AbstractClassB> AbstractClassA<? extends AbstractClassB>

您上面的评论似乎表明您不了解Java中子类型关系的这种差异限制。

如果没有显式类型转换,则无法将超类型指定为子类型。

在向下投射之前使用instanceof运算符。


尝试Class#isInstance()

abstract class AbstractClassA<T extends AbstractClassB> {}

abstract class AbstractClassB {}

class ClassAImpl<T extends AbstractClassB> extends AbstractClassA<T> {}

class ClassBImpl extends AbstractClassB {}

...

public static AbstractClassA<? extends AbstractClassB> myMethod() {
    return new ClassAImpl<ClassBImpl>();
}

...

AbstractClassA<? extends AbstractClassB> returnValue=myMethod();
if(returnValue.getClass().isInstance(new ClassAImpl<ClassBImpl>())){
    ClassAImpl<ClassBImpl> result=(ClassAImpl<ClassBImpl>)returnValue;
    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM