Java泛型:返回有界泛型类型

我遵循了这段代码:


public <T extends ParentException> T managedException(Exception cause) {        

    if(ExceptionA.class.isInstance(cause)) {

        return ExceptionA.class.cast(cause);

    } else if(ExceptionB.class.isInstance(cause)) {

        return ExceptionB.class.cast(cause);

    } else if(ExceptionC.class.isInstance(cause)){

        return ExceptionC.class.cast(cause);

    } else {

        return new ExceptionD(cause.getMessage(), cause);

    }

}

在这里ExceptionA,ExceptionB,ExceptionC,ExceptionD是儿童ParentException。


在编译时,我得到了错误:


incompatible types: ExceptionA cannot be converted to T

incompatible types: ExceptionB cannot be converted to T

incompatible types: ExceptionC cannot be converted to T

incompatible types: ExceptionD cannot be converted to T

但是,如果我将代码更改为:


@SuppressWarnings("unchecked")

public <T extends ParentException> T managedException(Exception cause) {        

    if(ExceptionA.class.isInstance(cause)) {

        return (T) ExceptionA.class.cast(cause);

    } else if(ExceptionB.class.isInstance(cause)) {

        return (T) ExceptionB.class.cast(cause);

    } else if(ExceptionC.class.isInstance(cause)){

        return (T) ExceptionC.class.cast(cause);

    } else {

        return (T) new ExceptionD(cause.getMessage(), cause);

    }

}

它没有编译错误。


正如 SO 线程的这个答案中提到的:How do I make the method return type generic? ,T允许使用 with进行转换,并且在此线程中给出了另一个指针:Java 泛型:泛型类型仅定义为返回类型。但我的问题是:当T有界并且所有返回的对象都落入指定的界限时,为什么我需要使用类型转换?


哈士奇WWW
浏览 135回答 3
3回答

慕哥9229398

你在做什么是错误的。这就是您收到错误的原因。你可以调用你的方法,ExceptionC exceptionC=managedException(ExceptionD d)你最终会得到一个(ExceptionC) exceptionD;强制转换并且强制转换它会掩盖错误,但你会在运行时得到它。将您的方法更改为:public ParentException managedException(Exception cause) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; if(ExceptionA.class.isInstance(cause)) {&nbsp; &nbsp; &nbsp; &nbsp; return ExceptionA.class.cast(cause);&nbsp; &nbsp; } else if(ExceptionB.class.isInstance(cause)) {&nbsp; &nbsp; &nbsp; &nbsp; return ExceptionB.class.cast(cause);&nbsp; &nbsp; } else if(ExceptionC.class.isInstance(cause)){&nbsp; &nbsp; &nbsp; &nbsp; return ExceptionC.class.cast(cause);&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; return new ExceptionD(cause.getMessage(), cause);&nbsp; &nbsp; }}这里不需要泛型。所有这些异常也是 ParentExceptions,所以你可以直接返回它们。当您考虑它时,您正在尝试使该方法返回不同的类型。不能那样做,因为如果你有一个从这个方法初始化的变量,你需要知道结果是什么。而且您知道结果将是 ParentException 但您不知道那是哪种父异常。其背后的原因是,您的方法如果编写为不返回 ParentException - 它返回 T (子类)。您可以返回不同类型的子类,而不是您想要获取的子类。在一个更简单的例子中,如果我们有:class A {}class B extends A{&nbsp; };class C extends A{&nbsp; };public&nbsp; <T extends A> T test() {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return (T) new B();}&nbsp; &nbsp;我们可以调用它C c=test();我们实际上尝试强制转换(C) new B();这是不兼容的但是我们已经屏蔽了它并且我们在运行时得到了异常

浮云间

因为ExceptionA&nbsp;a&nbsp;=&nbsp;managedException(new&nbsp;ExceptionB());将与ClassCastException.&nbsp;Java 推断T为,ExceptionA并且您的代码将进入这种B情况,这将导致错误的强制转换。Java 说它ExceptionC不是 a是正确的,T因为它T也可以是任何其他子类型ParentException。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java