我有以下代码:
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);
}
}
Here 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线程的这个答案中提到的:如何使方法返回类型通用? https://stackoverflow.com/a/450852/576758, 铸造T
是允许的,并且在此线程中给出了另一个指针:Java 泛型:泛型类型仅定义为返回类型 https://stackoverflow.com/q/338887/576758。但我的问题是:为什么我需要使用类型转换T
是有界的并且所有返回的对象都落入指定的范围内?
你所做的事情是错误的。这就是您收到错误的原因。您可以使用以下方式调用您的方法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);
}
}
这里不需要泛型。所有这些异常也是 ParentException,因此您可以直接返回它们。当您考虑它时,您正在尝试使该方法返回不同的类型。不能这样做,因为如果您有一个从此方法初始化的变量,您需要知道结果是什么。并且您知道结果将是 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();
这是不兼容的,但我们已经屏蔽了它,并且我们在运行时得到了异常
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)