首页 > 解决方案 > 需要 Java 的“更精确地重新抛出异常”

问题描述

我无法理解在 Java 7 及更高版本中精确重新抛出的工作原理。正如https://www.theserverside.com/tutorial/OCPJP-Use-more-precise-rethrow-in-exceptions-Objective-Java-7中所指出的 ,在 Java 7 及更高版本中,我们可以throws在方法声明,以逗号分隔的方法可能抛出的特定异常列表。如果所有这些异常都是一般异常的子类型java.lang.Exception,我们将能够在捕获此超类型的 catch 块中捕获它们中的任何一个,同时让客户端代码(例如调用者方法)知道实际发生了哪些可能的子类型异常.

最初,我认为为了让客户端代码知道实际发生了哪个异常,我们需要在throws子句中指定特定异常的列表。然而,在下面的示例中,客户端代码(main()方法)似乎能够检索该信息,即使我们仅在被调用方法java.lang.Exceptionthrows子句中指定异常。因此,我的问题是:

为什么不管throws方法的子句runException()throws ExceptionA, ExceptionBor ,下面的代码输出都一样throws Exception

我在 Eclipse 中使用 Oracle JVM-12。提前致谢!

class ExceptionA extends Exception{}
class ExceptionB extends Exception{}

public class RethrowingAndTypeChecking{
    public static void runException(char what) throws Exception{
    //public static void runException(char what) throws ExceptionA, ExceptionB{
        try{
            if(what == 'A') 
                throw new ExceptionA();
            else if (what == 'B')
                throw new ExceptionB();
        }
        catch(Exception e){
            throw e;
        }
    }

    public static void main (String args[]){
        char ch;
        for (int i=0;i<2;i++) {
            if(i==0) ch='A';
            else ch = 'B';

            try{
                runException(ch);
            }
            catch(ExceptionA e){
                System.out.print("In main(), 'catch(ExceptionA e){}', caught exception: " + e.getClass());
            }
            catch(ExceptionB e){
                System.out.print("In main(), 'catch(ExceptionB e){}', caught exception: " + e.getClass());
            }
            catch(Exception e){
                System.out.print("In main(), 'catch(Exception e){}', caught exception: " + e.getClass());
            }               
            System.out.println();
        }
    }
}

输出:

In main(), 'catch(ExceptionA e){}', caught exception: class ExceptionA
In main(), 'catch(ExceptionB e){}', caught exception: class ExceptionB

标签: javaexceptionrethrow

解决方案


您缺少的是您需要以不同方式处理这些可能的异常的情况。您的代码正在捕获个别异常,但粗略地说,它正在执行相同的操作。

如果您要以与处理ExceptionA方式截然不同的方式进行处理ExceptionB,那么捕捉广泛的Exception内容将不允许您专门这样做:

catch(Exception e){
    // something unexpected happened
    // e could be an ExceptionA problem
    // e could be an ExceptionB problem
    // e could be any other unchecked exception
}

当输入catch(Exception e){}块时,异常几乎可以是任何东西,但您只有一个通用代码块来处理它。

除此之外,如果您调用的方法声明了特定的检查异常,那么编译器可以帮助您仅处理这些异常,从而增加代码的可预测性

try{
    runException(ch);
} catch(ExceptionA e){
    // code specific to handling ExceptionA problems
} catch(ExceptionB e){
    // code specific to handling ExceptionB problems

} catch(ExceptionC e){ //will not compile, because not declared by runException
    // code specific to handling ExceptionB problems
}

推荐阅读