Java异常处理的10个最佳实践
异常处理在编写健壮的 Java 应用中扮演着非常重要的角色。异常处理并不是功能性需求,它需要优雅地处理任何错误情况,比如资源不可用、非法的输入、null 输入等等。Java 提供很多异常处理特性,通过内置的 try、catch、finally关键字实现。Java 同样允许创建新的异常和使用 throw 和 throws 抛出该异常。在实践中,异常处理不单单是知道语法这么简单。编写健壮的代码更像是一种艺术,而不是一门科学,在接下来的文章中,我们将讨论 Java 异常处理的最佳实践。这些最佳实践遵循标准的 JDK 库,以及几个开源代码库,来更好地应对错误和异常处理。这还是为 Java 程序员提供的编写健壮代码的袖珍参考手册。
编程中异常处理的最佳实践
这里是我收集的 Java 编程中异常处理的 10 个最佳实践。大家对 Java 中的受检异常(checked Exception)褒贬不一,这种语言特性要求该异常必须被处理。在本文中,我们尽可能少使用受检异常,同时也要学会在 Java 编程中,区别使用受检和非受检异常。
1)为可恢复的错误使用受检异常,为编程错误使用非受检异常。
对 Java 开发者来说,选择受检还是非受检异常总是让人感到困惑。受检异常保证你会针对错误情况提供异常处理代码,这是一种从语言层面上强制你编写健壮代码的一种方 式,但同时也引入大量杂乱的代码并导致其可读性变差。当然,如果你有可替代方式或恢复策略的话,捕获异常并做处理看起来似乎也合情合理。在 Java 编程中选择受检异常还是运行时异常的更多信息,请参考 checked vs unchecked exceptions。
2)在 finally 程序块中关闭或者释放资源
这是 Java 编程中一个广为人知的最佳实践和一个事实上的标准,尤其是在处理网络和 IO 操作的时候。在 finally 块中关闭资源能保证无论是处于正常还是异常执行的情况下,资源文件都能被合理释放,这由 finally 语句块保证。从 Java7 开始,新增加了一项更有趣的功能:自动资源管理,或者称之为ARM块。尽管如此,我们仍然要记住在 finally 块中关闭资源,这对于释放像 FileDescriptors 这类资源至关重要,因为它在 socket 和文件操作中都会被用到。
3)在堆栈信息中包含引起异常的原因
Java 库和开源代码在很多情况下会将一种异常包装成另一种异常。这样记录和打印根异常就变得非常重要。Java 异常类提供了 getCause() 方法来获取导致异常的原因,这可以提供更多有关异常发生的根本原因的信息。这条实践对调试或排除故障大有帮助。在把一个异常包装成另一种异常时,记住需要 把源异常传递给新异常的构造器。
4)始终提供异常的有意义的完整信息
异常信息是最重要的,在其中,你能找到问题产生的原因,因为这是出问题后程序员最先看到的地方。记得始终提供精确的真实的信息。例如,对比下面两条 IllegalArgumentException 的异常信息:
message 1: “Incorrect argument for method” message 2: “Illegal value for ${argument}: ${value}
第一条消息仅说明了参数是非法的或不正确的,但第二条消息包括了参数名和非法值,这对找到错误原因很重要。在编写异常处理代码的时候,应当始终遵循该 Java 最佳实践。
5)避免过度使用受检异常
受检异常的强制性在某种程度上具有一定的优势,但同时它也使得代码可读性变差,混淆了正常的业务逻辑代码。你可以通过适度使用受检异常来最大限度地 减少这类情况的发生,这样可以得到更简洁的代码。你同样可以使用 Java7 的新功能,比如在一个catch语句中捕获多个异常,以及自动管理资源,以此来移除一些冗余的代码。
6)将受检异常转为运行时异常
这是在诸如 Spring 之类的框架中用来减少使用受检异常的方式之一,大部分 JDBC 的受检异常都被包装进 DataAccessException 中,DataAccessException异常是一种非受检异常。这个最佳实践带来的好处是可以将特定的异常限制到特定的模块中,比如把 SQLException 抛到 DAO 层,把有意义的运行时异常抛到客户端层。
7)记住异常的性能代价高昂
需要记住的一件事是异常代价高昂,同时让代码运行缓慢。假如你有一个方法从 ResultSet 中进行读取,它经常会抛出 SQLException 而不是将 cursor 移到下一元素,这将会比不抛出异常的正常代码执行的慢的多。因此最大限度的减少不必要的异常捕捉,去修复真正的根本问题。不要仅仅是抛出和捕捉异常,如果 你能使用 boolean 变量去表示执行结果,可能会得到更整洁、更高性能的解决方案。修正错误的根源,避免不必要的异常捕捉。
8)避免空的 catch 块
没有什么比空的 catch 块更糟糕的了,因为它不仅隐藏了错误和异常,同时可能导致你的对象处于不可用状态或者脏状态。空的 catch 块没有意义,除非你非常肯定异常不会以任何方式影响对象的状态,但在程序执行期间,用日志记录错误依然是最好的方法。这在 Java 异常处理中不仅仅是一个最佳实践,而且是一个最通用的实践。
9)使用标准异常
第九条最佳实践是建议使用标准和内置的 Java 异常。使用标准异常而不是每次创建我们自己的异常,这对于目前和以后代码的可维护性和一致性,都是最好的选择。重用标准异常使代码可读性更好,因为大部分 Java 开发人员对标准的异常更加熟悉,比如 JDK 中的 RuntimeException,IllegalStateException,IllegalArgumentException,NullPointerException, 他们能立马知道每种异常的目的,而不是在代码或文档里查找用户自定义异常的目的。
10)为方法抛出的异常编写文档
Java 提供了 throw 和 throws 关键字来抛出异常,在 javadoc 中可以用@throw 为任何可能被抛出的异常编写文档。如果你编写 API 或者公共接口,这就变得非常重要。当任何方法抛出的异常都有相应的文档记录时,就能潜在的提醒任何调用该方法的开发者。
以上这些就是所有在 Java 异常处理需要遵循的最佳实践。如果你有异常处理更好的最佳实践,请务必让我们知道。
Java异常处理的10个最佳实践的更多相关文章
- 《转载》Java异常处理的10个最佳实践
本文转载自 ImportNew - 挖坑的张师傅 异常处理在编写健壮的 Java 应用中扮演着非常重要的角色.异常处理并不是功能性需求,它需要优雅地处理任何错误情况,比如资源不可用.非法的输入.nul ...
- Java 编程中关于异常处理的 10 个最佳实践
异常处理是Java 开发中的一个重要部分.它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java提供了几个异常处理特性,以try,catch 和 ...
- Java异常处理的9个最佳实践
无论你是新手还是资深程序员,复习下异常处理的实践总是一件好事,因为这能确保你与你的团队在遇到问题时能够处理得了它. 在 Java 中处理异常并不是一件易事.新手觉得处理异常难以理解,甚至是资深开发者也 ...
- Java 异常处理的 9 个最佳实践
在 Java 中,异常处理是个很麻烦的事情.初学者觉得它很难理解,甚至是经验丰富的开发者也要花费很长时间决定异常是要处理掉和抛出. 所以很多开发团队约定一些原则处理异常.如果你是一个团队的新成员,你可 ...
- Java 异常处理的 20 个最佳实践,你知道几个?
异常处理是 Java 开发中的一个重要部分,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java 提供了几个异常处理特性,以try,catch 和 finally 关键字的形式内建 ...
- jenkins2 pipeline插件的10个最佳实践
jenkins pipeline的10个最佳实践. 文章来自:http://www.ciandcd.com文中的代码来自可以从github下载: https://github.com/ciandcd ...
- restful api的10个最佳实践
Web API在过去的几年里非常盛行,因为它有着语法简单.规范化和轻量级的优点,因为得到广泛的推崇,很多过往的技术手段都慢慢转换为使用Web API来开发.而Web API通常使用的设计方式是REST ...
- Java异常处理 10 个最佳实践
异常处理是Java 开发中的一个重要部分.它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java提供了几个异常处理特性,以try,catch 和 ...
- Java 服务 Docker 容器化最佳实践
转载自:https://mp.weixin.qq.com/s/d2PFISYUy6X6ZAOGu0-Kig 1. 概述 当我们在容器中运行 Java 应用程序时,可能希望对其进行调整参数以充分利用资源 ...
随机推荐
- Eclipse debug neutron-server
1 首先停掉neutron-server kill neutron-server in screen by ctr-c q-svc 2 cp /usr/local/bin/neutron-server ...
- tkinter模块中常用的参数
以下内容来自于:http://www.cnblogs.com/aland-1415/p/6849193.html(个别内容掺入了自己的重新整理) cnf={}与**kw: cnf={}这是一个默认参数 ...
- Oracle数据库的三种验证机制
关于超级管理员登陆不需要密码因为: 数据库的三种验证机制: 操作系统验证(具有sysdba和sysopera的用户) 密码文件验证(具有sysdba和sysopera的用户) 数据库验证(普通用户) ...
- Python — pandas
Pandas有两种数据结构:Series和DataFrame. 1.Series Series类似于一维数组,和numpy的array接近,由一组数据和数据标签组成.数据标签有索引的作用.数据标签是p ...
- 如何理解Box-sizing模型?
CSS3 box-sizing 属性 http://www.w3school.com.cn/tiy/t.asp?f=css3_box-sizing <style> div.containe ...
- VS2019(Windows+Mac)编辑文件模板
macOS 找到设置中的如图条目 设置如下内容: ============================================================ Copyright (C) ...
- linux命令学习笔记(59):rcp命令
rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝:第二种格式用于把文件或目录拷贝到另一个目录中. . ...
- Android 中对于图片的内存优化方法
Android 中对于图片的内存优化方法,需要的朋友可以参考一下 1. 对图片本身进行操作 尽量不要使用 setImageBitmap.setImageResource. BitmapFact ...
- Java进阶07 嵌套类
到现在为止,我们都是在Java文件中直接定义类.这样的类出现在包(package)的级别上.Java允许类的嵌套定义. 这里将讲解如何在一个类中嵌套定义另一个类. 嵌套 内部类 Java允许我们在类的 ...
- 本地未安装Oracle数据库,如何连接远程Oracle数据库
方法一:用Navicat Premium连接 注意,这里用的要是黄色的版本,而不是只针对Mysql的绿色版本 工具栏选择[工具]-[选项],点击[其他-OCI] 你会发现有个OCI librar ...