Java 代理和未声明的HrowableException

Java 代理和未声明的HrowableException,java,Java,我想问的是,为什么当代码运行指令instance.run(new IOException())时,它会抛出未声明的hrowableexception 根据oracle的文档,在InvocationHandler的invoke方法中,如果此方法引发了一个选中的异常,该异常不可分配给接口方法的throws子句中声明的任何异常类型,然后,代理实例上的方法调用将引发包含此方法引发的异常的未声明的HrowableException 在这种情况下,IOException与IOException相似,那么为什

我想问的是,为什么当代码运行指令instance.run(new IOException())时,它会抛出未声明的hrowableexception

根据oracle的文档,在InvocationHandler的invoke方法中,如果此方法引发了一个选中的异常,该异常不可分配给接口方法的throws子句中声明的任何异常类型,然后,代理实例上的方法调用将引发包含此方法引发的异常的未声明的HrowableException

在这种情况下,IOException与IOException相似,那么为什么它会抛出未声明的HrowableException而不是IOException?

因为当您从具有相似方法签名的两个接口创建代理时,这些方法签名将合并为满足两个接口要求的一个签名

由于
eofeexception
继承自
IOException
方法签名将

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();
    }
}
您可以通过创建虚拟类来测试这一点:

public Object run(Throwable toThrow) throws EOFException
这是因为您可以缩小抛出的异常范围(使用
抛出EOFEException
覆盖
抛出IOException
很好),但不能扩大它(使用
抛出IOException
覆盖
抛出EOFEException
是非法的)


因此,当您调用该方法并抛出
EOFEException
时,它符合代理生成的方法签名(声明了该签名),并且一切正常。但是,当您抛出
IOException
时,它与签名不符(未声明),并且您得到
未声明的HrowableException
,谢谢,但是如果两个接口无法合并,会发生什么情况呢?
newProxyInstance
将抛出
IllegalArgumentException
我在oracle文档中找到了答案,关于“方法在多个代理接口中重复”,但仍然感谢您的帮助。
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;
    }
}