Java 中有关于异常传播的指南吗?
什么时候向方法签名添加异常?
例如:如果仅在缺少必要的程序资源时抛出异常,并且只能在顶层处理,那么我是否可以通过使用错误方法的所有方法将其传播到使用此异常的所有方法?
有什么好的做法吗?有什么不好的做法吗?
如果我含糊其辞,我很抱歉,但我只是在寻找有关异常的编程风格的一些(一般)建议。
过去对我有帮助的指导方针包括:
-
当方法无法处理异常时抛出异常,更重要的是,应该由调用者处理。 Servlet API 中出现了一个很好的例子 - doGet() 和 doPost() 在某些无法正确读取请求的情况下抛出 ServletException 或 IOException。这些方法都无法处理异常,但容器可以(在大多数情况下会导致 50x 错误页面)。
-
如果方法无法处理异常,则将异常冒泡。这是上述的推论,但适用于必须捕获异常的方法。如果该方法无法正确处理捕获的异常,那么最好将其冒泡。
-
立即抛出异常。这可能听起来很模糊,但如果遇到异常情况,那么最好抛出一个异常来指示原始故障点,而不是尝试通过错误代码处理故障,直到认为适合抛出异常的点。换句话说,尝试尽量减少异常处理与错误处理的混合。
-
要么记录异常,要么冒泡,但不要同时执行这两种操作。记录异常通常表明异常堆栈已完全展开,表明没有发生进一步的异常冒泡。因此,不建议同时执行这两项操作,因为这通常会导致调试过程中出现令人沮丧的体验。
-
使用子类java.lang.Exception http://download.oracle.com/javase/6/docs/api/java/lang/Exception.html(检查异常),当你排除调用者来处理异常时。如果调用者不处理异常,这会导致编译器抛出错误消息。但请注意,这通常会导致开发人员“吞下”代码中的异常。
-
使用子类java.lang.RuntimeException http://download.oracle.com/javase/6/docs/api/java/lang/RuntimeException.html(未经检查的异常)表示编程错误。这里推荐的异常类包括非法状态异常 http://download.oracle.com/javase/6/docs/api/java/lang/IllegalStateException.html, 非法参数异常 http://download.oracle.com/javase/6/docs/api/java/lang/IllegalArgumentException.html, 不支持的操作异常 http://download.oracle.com/javase/6/docs/api/java/lang/UnsupportedOperationException.html再次强调,必须小心使用像 NullPointerException 这样的异常类(抛出异常类几乎总是一种不好的做法)。
-
使用异常类层次结构跨各个层传达有关异常的信息。通过实现层次结构,您可以概括调用者中的异常处理行为。例如,您可以使用像 DomainException 这样的根异常,它有几个子类,如 InvalidCustomerException、InvalidProductException 等。这里需要注意的是,如果您将每个单独的异常场景表示为单独的异常,则异常层次结构可能会很快爆炸。
-
避免捕获无法处理的异常。很明显,但许多开发人员尝试捕获 java.lang.Exception 或 java.lang.Throwable。由于可以捕获所有子类异常,因此当捕获“全局”异常类时,应用程序的运行时行为通常会很模糊。毕竟,人们不想捕获 OutOfMemoryError - 应该如何处理这样的异常?
-
小心包裹异常。重新抛出异常会重置异常堆栈。除非已将原始原因提供给新的异常对象,否则它将永远丢失。为了保留异常堆栈,必须向新异常的构造函数提供原始异常对象。
-
仅在需要时将检查异常转换为未检查异常。包装异常时,可以包装已检查的异常并抛出未检查的异常。这在某些情况下很有用,特别是当目的是中止当前正在执行的线程时。但是,在其他情况下,这可能会导致一些麻烦,因为不执行编译器检查。因此,将受检异常调整为非受检异常并不意味着盲目地进行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)