Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用嵌套异常是一种好的做法吗?_Java_Exception_Exception Handling - Fatal编程技术网

Java 使用嵌套异常是一种好的做法吗?

Java 使用嵌套异常是一种好的做法吗?,java,exception,exception-handling,Java,Exception,Exception Handling,这可能是一个宽泛的问题,不是很有风格,但如果可能的话,我仍然想得到一些提示或指导 我一直在查看一些遗留代码,发现其中有一部分包含嵌套了3或4级异常的方法。 这是一种正常的做法,还是应该尽可能避免这种代码风格?如果应该避免,除了增加异常处理成本和降低可读性之外,还有什么负面影响?有没有常见的重构代码的方法来避免这种情况?您应该取消异常嵌套。您应该首先避免链接异常,或者(有选择地)先展开嵌套异常,然后再在堆栈上进一步重推嵌套异常。关于处理遗留代码,我建议您看一看涵盖以下主题的书: 你甚至不必通读整本

这可能是一个宽泛的问题,不是很有风格,但如果可能的话,我仍然想得到一些提示或指导

我一直在查看一些遗留代码,发现其中有一部分包含嵌套了3或4级异常的方法。

这是一种正常的做法,还是应该尽可能避免这种代码风格?如果应该避免,除了增加异常处理成本和降低可读性之外,还有什么负面影响?有没有常见的重构代码的方法来避免这种情况?

您应该取消异常嵌套。您应该首先避免链接异常,或者(有选择地)先展开嵌套异常,然后再在堆栈上进一步重推嵌套异常。

关于处理遗留代码,我建议您看一看涵盖以下主题的书: 你甚至不必通读整本书,只要看看此刻与你有关的事情就行了

关于良好实践的好书还有:


处理嵌套异常的最佳方法是重构代码,使用运行时而不是检查异常,并在需要时处理这些异常。这样,代码更易于阅读和维护。

它取决于业务逻辑。您可以对异常本身采取操作,也可以将异常一直传播到调用方,并将其留给调用方执行他想要的操作

e、 有很多第三方API不处理异常,但它们从方法中抛出异常,从而方便API用户根据需要采取行动


e、 OracleJDBC驱动程序。getConnection()引发异常。现在,调用者/API用户可以根据需要处理它。您可以只打印堆栈跟踪,也可以通知管理员请求其注意,或者选择仅以静默方式退出应用程序。

如果可能,检查的异常不应传播到堆栈或链接。若一个方法抛出一个已检查的异常,它的调用者应该处理它,若调用者并没有处理它并将它传播给它的调用者,那个么总体复杂性会增加

在一个三层示例中:Dao、服务、控制器

DAO层将抛出DAO异常
服务层不应该向控制器公开DAOException,相反,它应该抛出控制器应该处理的相关BuinessException。

异常处理往往是处理流控制的昂贵方式(当然对于C#和Java而言)

当构造异常对象时,运行时会做大量的工作——将堆栈跟踪放在一起,找出处理异常的位置等等

如果使用流控制语句进行流控制,则不需要扩展内存和CPU资源中的所有这些成本

此外,还有一个语义问题。例外情况适用于例外情况,而非正常流量控制。我们应该使用异常处理来处理意外/异常情况,而不是像正常的程序流那样,因为否则,一个未捕获的异常将告诉您更少的信息

除此之外,还有其他人阅读代码的问题。以这种方式使用异常并不是大多数程序员所期望的,因此代码的可读性和可理解性受到影响。当一个人看到“例外”时,他会想——一些不好的事情发生了,一些不应该正常发生的事情。因此,以这种方式使用异常非常容易混淆

请看下面的链接


我个人更喜欢以下意识形态

包装外来异常

“外来”异常是Java API或第三方库引发的异常。换句话说,一个您无法控制的异常

最好捕获所有外来异常,并将它们封装在适当的特定于应用程序的异常中。一旦外来异常转换为您自己的异常,您就可以以任何方式传播该异常

重新搜索选中的异常可能会变得混乱

如果应用程序使用选中的异常,则重新引用原始异常意味着重新引用它的方法也必须声明它

越接近调用层次结构的顶部,就会抛出越多的异常。除非您只是声明所有要抛出异常的方法。但是,如果您这样做,您也可以使用未经检查的异常,因为您实际上并没有从编译器异常检查中获得任何好处

这就是为什么我喜欢捕获非应用程序特定的异常,并在将它们传播到调用堆栈之前将它们包装到应用程序特定的异常中

包装指南:异常发生的上下文可能与异常本身的位置一样重要。应用程序中的给定位置可以通过不同的执行路径访问,如果发生错误,执行路径可能会影响错误的严重性和原因

如果在向调用堆栈上传播异常时需要向异常添加上下文信息,则需要使用主动传播。换句话说,您需要在调用堆栈上的各个相关位置捕获异常,并在重新引用或包装它之前向其添加相关上下文信息

public void doSomething() throws SomeException{

    try{

        doSomethingThatCanThrowException();

    } catch (SomeException e){

       e.addContextInformation(“more info”);
       throw e;  //throw e, or wrap it – see next line.

       //throw new WrappingException(e, “more information”);

    } finally {
       //clean up – close open resources etc.
    }

}

有两种方法:

To generate a separate exception for each event.
To create a generic exception and describe what caused it 
第一种方法允许您编写不同的代码来处理不同的事件,但它需要您编写大量的异常类,在某些情况下可能会太多

第二种方法更简洁,但它使处理不同情况变得困难

由于编程中经常出现,最好的解决方案是在中间,在这里平衡生成单独的异常,并在其他情况下使用一个异常。

经验法则
catch (Throwable e) {
throw new CommandExecutorException(e);
}
} catch (ClassCastException e1) {
 ...
} catch (FileNotFoundException e) {
... 
} catch (IOException e) {
...
}