异常传播指南(Java)

wen*_*wen 41 java exception-handling exception

Java中的异常传播是否有任何指导原则?

什么时候为方法签名添加例外?例如:如果仅在缺少基本程序资源时抛出异常,并且只能在顶层处理异常,那么使用错误方法通过所有方法使用此异常将其传播到所有方法吗?

有什么好的做法吗?任何不良做法?

我很抱歉,如果我是模糊的,但我只是在寻找有关异常的编程风格的一些(一般)建议.

Vin*_*lds 52

过去帮助过我的指南包括:

  • 当方法无法处理异常时抛出异常,更重要的是,应由调用者处理.Servlet API中出现了一个很好的例子 - 在无法正确读取请求的某些情况下,doGet()和doPost()会抛出ServletException或IOException.这些方法都不能处理异常,但是容器是(在大多数情况下导致50x错误页面).
  • 如果方法无法处理,则冒泡异常.这是上述的推论,但适用于必须捕获异常的方法.如果该方法无法正确处理捕获的异常,则最好将其冒泡.
  • 立即抛出异常.这可能听起来很模糊,但如果遇到异常情况,那么抛出指示原始故障点的异常是一种好习惯,而不是尝试通过错误代码处理故障,直到认为适合抛出异常的点为止. .换句话说,尝试最小化混合异常处理和错误处理.
  • 记录异常或冒泡,但不要同时执行这两种操作.记录异常通常表示异常堆栈已完全展开,表明没有发生异常的冒泡.因此,不建议同时执行这两项操作,因为这通常会导致令人沮丧的调试经验.
  • 当调用者除了处理异常时,使用java.lang.Exception的子类(已检查的异常).如果调用者不处理异常,则会导致编译器抛出错误消息.但要注意,这通常会导致开发人员在代码中"吞噬"异常.
  • 使用java.lang.RuntimeException(未经检查的异常)的子类来表示编程错误.这里推荐的异常类包括IllegalStateException,IllegalArgumentException,UnsupportedOperationException等.同样,必须注意使用NullPointerException等异常类(几乎总是一个不好的做法抛出一个).
  • 使用异常类层次结构来跨多个层传递有关异常的信息.通过实现层次结构,您可以概括调用者中的异常处理行为.例如,您可以使用像DomainException这样的根异常,它有几个子类,如InvalidCustomerException,InvalidProductException等.这里需要注意的是,如果将每个单独的异常方案表示为单独的异常,则异常层次结构可能会非常快速地爆炸.
  • 避免捕捉无法处理的异常.很明显,但很多开发人员试图捕获java.lang.Exception或java.lang.Throwable.由于可以捕获所有子类异常,因此当捕获"全局"异常类时,应用程序的运行时行为通常很模糊.毕竟,人们不想捕获OutOfMemoryError - 应该如何处理这样的异常?
  • 小心包装异常.重新抛出异常会重置异常堆栈.除非原始原因已提供给新的异常对象,否则它将永远丢失.为了保留异常堆栈,必须将原始异常对象提供给新异常的构造函数.
  • 仅在需要时将已检查的异常转换为未经检查的异常.包装异常时,可以包装已检查的异常并抛出未经检查的异常.这在某些情况下很有用,特别是当意图中止当前正在执行的线程时.但是,在其他情况下,这可能会导致一些痛苦,因为不会执行编译器检查.因此,将检查的异常作为未经检查的异常进行调整并不是盲目地进行的.

  • 我不同意在重新抛出异常时丢失细节. (4认同)