繁体   English   中英

Java异常处理的最佳实践

[英]Best practice for Java exception handling

我最近写了下面的代码; 它使用了很多异常处理。 我认为它使代码看起来非常难以理解。 我可以通过捕获泛型异常来缩短代码,例如

catch (Exception e){
    e.printStackTrace();
}

但我也听说过捕获一般异常不是一个好的编码实践。

public class DataAnalyzerTester {
    /**
     * @param args args[0] stores the filename
     * @exception NoSuchElementException if user attempts to access empty list element
     * @exception ArithmeticException if user attempts to divide by 0
     * @exception ArrayIndexOutOfBoundsException if user supplied less than 3 arguments
     * @exception IOException problems with creating and writing files
     * @exception RuntimeException if user attempts to pass empty list to constructor
     */
    public static void main(String[] args) {

    try{
        //some code

    } catch (NoSuchElementException e) {
        System.out.println("Accessing element that does not exist: " + e.toString());
    } catch (ArithmeticException e) {
        System.out.println("Division by zero: " + e.toString());
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Please supply a command line arguement that specifies your file path: " + e.toString());
    } catch (IOException e) {
        System.out.println("Other IO errors: " + e.toString());
    } catch (RuntimeException e) {
        System.out.println(e.toString());
    } 
    }
}

我想知道是否有更好,更清晰的方法来捕获多个异常。

首先,除非你有很好的理由, 永远赶不上RuntimeExceptionExceptionThrowable 这些将赶上抛出任何东西,和Throwable会抓住一切 ,即使是那些你不打算赶,喜欢的东西OutOfMemoryError

其次,避免捕获运行时异常,除非它直接阻碍程序的关键操作。 (但严重的是,如果有人看到你发现了NullPointerException ,那么他们完全有权在你身上打电话给你。)你唯一需要注意的例外是那些你需要处理的例外。 在您的异常列表中,您唯一应该打扰的是IOException 其余的是没有足够的测试或草率编码的结果; 那些不应该在您的应用程序的正常运行时间内发生。

第三,在Java 7中,如果异常是互斥的,您可以为异常执行多捕获语句。 链接的示例很好地解释了它,但如果您遇到同时IOExceptionSQLException ,您可以像这样处理它:

try {
    // Dodgy database code here
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

这会清理一些事情,因为你没有笨拙和庞大的异常链。

首先,“最佳实践”建议的问题在于它倾向于过度简化问题和答案。 然后有人(像你一样)出现并注意到它是矛盾的。

国际海事组织,最佳做法是采取“最佳做法”建议和经常使用该词组的人怀疑健康。 尝试自己理解真正的问题,并得出自己的结论......而不是仅仅依靠别人告诉你什么是“最佳实践”。


那么这里的问题是什么? 这是声明:

但我也听说过捕获一般异常不是一个好的编码实践。

实际上,捕获像Exception这样的泛型异常通常不是一种好的编码实践。 但在某些情况下这是正确的做法。 你的例子就是适当的例子。

为什么?

好吧,让我们看看捕获Exception是一个坏主意:

    public void doSomething(...) {
        try {
            doSomethingElse(...);
        } catch (Exception ex) {
            // log it ... and continue
        }
    }

为什么这是一个坏主意? 因为这个catch将捕获和处理意外的异常; 即您(开发人员)认为不可能的例外,或者您甚至没有考虑的例外情况。 没关系...但是代码会记录异常,并继续运行,好像什么都没发生一样。

这是真正的问题...... 试图从意外的异常中恢复

(从不捕获通用异常)的(所谓的)“最佳实践”建议涉及该问题,但是以粗略的方式处理边缘情况。 其中一个边缘情况是,如果您立即关闭应用程序,捕获(并记录)一般异常就行了......就像您正在做的那样。

    public void main(...) {
        try {
            // ...
        } catch (Exception ex) {
            // log exception
            System.err.println("Fatal error; see log file");
            System.exit(1);
        }
    }

现在将其与你问题中的(假定的)良好练习版本进行对比。 有什么不同?

  1. 您的版本产生了更多用户友好/警报更少的诊断......在某种程度上。
  2. 您的版本代码明显更多。
  3. 您的版本对于尝试诊断问题的人没有帮助,因为没有记录堆栈跟踪。

与1和2的对应点是:

  1. 您可以花费无限的时间为应用程序进行“用户友好”诊断,但仍然无法帮助那些不能或不会理解的用户......
  2. 它还取决于典型用户是谁。

正如您所看到的,这比“捕获通用异常是不良做法”更加微妙。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM