为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

哈士奇WWW 2021-07-24 19:01:08
我遵循了这段代码: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 Tincompatible types: ExceptionB cannot be converted to Tincompatible types: ExceptionC cannot be converted to Tincompatible 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有界并且所有返回的对象都落入指定的界限时,为什么我需要使用类型转换?
查看完整描述

3 回答

?
慕哥9229398

TA贡献1877条经验 获得超6个赞

你在做什么是错误的。这就是您收到错误的原因。你可以调用你的方法,ExceptionC exceptionC=managedException(ExceptionD d)你最终会得到一个(ExceptionC) exceptionD;强制转换并且强制转换它会掩盖错误,但你会在运行时得到它。


将您的方法更改为:


public ParentException 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);

    }

}

这里不需要泛型。所有这些异常也是 ParentExceptions,所以你可以直接返回它们。当您考虑它时,您正在尝试使该方法返回不同的类型。不能那样做,因为如果你有一个从这个方法初始化的变量,你需要知道结果是什么。而且您知道结果将是 ParentException 但您不知道那是哪种父异常。


其背后的原因是,您的方法如果编写为不返回 ParentException - 它返回 T (子类)。您可以返回不同类型的子类,而不是您想要获取的子类。


在一个更简单的例子中,如果我们有:


class A {}


class B extends A{  };


class C extends A{  };


public  <T extends A> T test() {        

        return (T) new B();

}   

我们可以调用它C c=test();我们实际上尝试强制转换(C) new B();这是不兼容的但是我们已经屏蔽了它并且我们在运行时得到了异常


查看完整回答
反对 回复 2021-07-29
?
浮云间

TA贡献1829条经验 获得超4个赞

因为

ExceptionA a = managedException(new ExceptionB());

将与ClassCastException. Java 推断T为,ExceptionA并且您的代码将进入这种B情况,这将导致错误的强制转换。

Java 说它ExceptionC不是 a是正确的,T因为它T也可以是任何其他子类型ParentException


查看完整回答
反对 回复 2021-07-29
  • 3 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信