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的doc,在InvocationHandler的invoke方法中,如果此方法抛出了一个被检查的异常,该异常不能分配给接口方法的throws子句中声明的任何异常类型然后,代理实例上的方法调用将抛出包含此方法引发的异常的UndeclaredThrowableException。
在这种情况下,IOException对IOException是可以的,那么为什么它会抛出UndeclaredThrowableException而不是IOException?
答案 0 :(得分:0)
因为当您从具有类似方法签名的两个接口创建代理时,这些方法签名将合并到一个签名,以满足两个接口的要求。
由于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
时,它适合代理生成的方法签名(它被声明),一切都很好。但是当你抛出IOException
时它不符合签名(它没有被声明),你得到UndeclaredThrowableException
。