问题描述
首先,我应该说我能够获得实例或匿名内部类的通用类型.
First, I should say that I am able to get the generic type of instances or anonymous inner classes.
这是代码示例,查找catch块:
public static interface MyInterface<E extends Throwable>{
void call() throws E;
}
public static <E extends Throwable> void method(MyInterface<E> lambda) throws E {
try {
lambda.call();
} catch(Throwable ex) {
// Pseudo code
Class<?> T = ((ParameterizedType)ex.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
if ( T.isInstance(ex) ) {
throw ex;
} else {
...
}
}
}
public static void throwsException() throws Exception {
throw new Exception();
}
这不起作用:
method(() -> {
throwsException();
});
但是这样做:
method(new MyInterface<Exception>() {
@Override
public void call() throws Exception {
throwsException();
}
});
但是随着Lambdas的引入,我不能再强制执行此操作了!
But with the introduction of Lambdas, i can no longer enforce this!
还应注意,这现在可能会破坏与<之前的库的向后兼容性. 8,并反映出此信息.
It should also be noted that this now potentially breaks backwards compatibility with Libraries older than < 8, and that reflected out this information.
我已经研究了这个主题,并且似乎只有可能的变通方法来获取方法参数,但这是关于抛出部分的,因此将无法正常工作.
I have researched this topic, and there only seems to be possible workarounds for getting the method parameters, but this is regarding the throws part so that won't work.
注意:我已经看过此主题了:在Java 8 Lambda上的反射类型推断
推荐答案
您只需编写
public static interface MyInterface<E extends Throwable>{
void call() throws E;
}
public static <E extends Throwable> void method(MyInterface<E> lambda) throws E {
try {
lambda.call();
}
catch(Throwable ex) {
throw ex;
}
}
无需处理反射.由于保证MyInterface<E>.call()
仅抛出可分配给E
的类型或未经检查的异常,因此很明显,捕获的ex
必须是可分配给E
的类型或未经检查的异常,因此可以安全地重新执行-抛出.
without dealing with Reflection. Since MyInterface<E>.call()
is guaranteed to throw types assignable to E
or unchecked exceptions only, it is clear that the catched ex
must be either of a type assignable to E
or an unchecked exception, hence may be safely re-thrown.
从Java 7开始有效.
This works since Java 7.
相反,如果您的方法执行其他操作可能会引发不能保证与E
兼容的异常,则应显式声明它们,而不要进行反射魔术.否则,您将有一种方法以一种奇怪的方式更改其行为,因为该方法取决于参数,是简单地引发还是以不同的方式处理特定的异常类型(包装或其他后备行为).
In contrast, if your method performs other operations which may throw exceptions not guaranteed to be compatible with E
, you should declare them explicitly rather than doing Reflection magic. Otherwise you have a method changing its behavior in a strange way as it depends then on the parameter whether a particular exception type is simply thrown or handled differently (wrapped or whatever your fall-back behavior is).
请注意,您的反射魔法还是被破坏了.考虑这个简单的例子:
Note that your Reflection magic is broken anyway. Consider this simple example:
class Foo<E extends Throwable> implements MyInterface<E> {
public void call() throws E {
}
}
直接实例化此类时,您无法在运行时通过反射获取实际的类型参数.这与通过lambda表达式创建的实现完全相同.
when instantiating this class directly, you can’t get the actual type arguments at runtime via Reflection. This is exactly the same behavior as with implementations created via lambda expressions.
这篇关于Java:获取lambda的通用类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!