java - 代理和 UndeclaredThrowableException
问题描述
import java.io.EOFException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public class ProxyDemo {
private final ClassLoader loader = getClass().getClassLoader();
private final InvocationHandler throwHandler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
throw (Throwable) args[0];
}
};
public interface ThrowsIOException {
Object run(Throwable toThrow) throws IOException;
}
public interface ThrowsEOFException {
Object run(Throwable toThrow) throws EOFException;
}
public void testDeclaredExceptionIntersectionIsSubtype() throws Exception {
ThrowsIOException instance = (ThrowsIOException) Proxy.newProxyInstance(loader,
new Class[] {ThrowsIOException.class, ThrowsEOFException.class}, throwHandler);
try {
instance.run(new EOFException());
} catch (EOFException expected) {
}
try {
instance.run(new IOException());
} catch (UndeclaredThrowableException expected) {
}
try {
instance.run(new Exception());
} catch (UndeclaredThrowableException expected) {
}
}
public static void main(String[] args) throws Throwable {
ProxyDemo cl = new ProxyDemo();
cl.testDeclaredExceptionIntersectionIsSubtype();
}
}
我想问的是为什么当代码运行指令instance.run(new IOException())时,它会抛出UndeclaredThrowableException?
根据 oracle 的文档,在 InvocationHandler 的调用方法中,如果该方法抛出了一个检查的异常,该异常不能分配给接口方法的 throws 子句中声明的任何异常类型,则一个 UndeclaredThrowableException 包含由抛出的异常此方法将由代理实例上的方法调用抛出。
在这种情况下,IOException 对 IOException 是可以处理的,那么为什么它会抛出 UndeclaredThrowableException 而不是 IOException?
解决方案
因为当您从具有相似方法签名的两个接口创建Proxy时,这些方法签名将合并为一个满足两个接口要求的签名。
由于EOFException
从方法签名继承IOException
将是
public Object run(Throwable toThrow) throws EOFException
您可以通过创建虚拟类来自己测试:
public class Test implements ThrowsIOException, ThrowsEOFException {
@Override
public Object run(Throwable toThrow) throws IOException // compiler error
{
return null;
}
}
public class Test implements ThrowsIOException, ThrowsEOFException {
@Override
public Object run(Throwable toThrow) throws EOFException // valid
{
return null;
}
}
这是因为你可以缩小抛出的异常(用覆盖throws IOException
很好throws EOFException
),但你不能扩大它(用覆盖throws EOFException
是throws IOException
非法的)。
因此,当您调用该方法并EOFException
抛出 a 时,它符合代理生成的方法签名(已声明)并且一切都很好。但是,当您抛出IOException
它时,它不符合签名(未声明)并且您得到UndeclaredThrowableException
.
推荐阅读
- php - mysql数据库的PHP未定义索引错误
- python - 为什么字符串乘法的字节码不同?
- excel - 在 selenium VBA 中使用 datepicker 插入日期
- python - 如何在 Pyqt5 的 QMainWindow 中将小部件放在背景图像上?
- python - DJANGO - 如何从同一表单内的其他 Select 字段动态填充/过滤 Select 字段
- java - Android - 如何以可读的方式链接多个异步方法
- artificial-intelligence - 我的 CLIPS 代码有什么不好的 - 或/和变化或 else-if 语法?
- r - case_when 在 mutate 函数中出错:输入必须是向量
- python - 在python中将所有零移动到数组的末尾
- javascript - 删除 Firebase 中除个人数据外的先前字段