Java Exception最佳实践(转)
https://www.dubby.cn/detail.html?id=9033
- 1.异常介绍
- 2.Java中的异常介绍
- 3.自定义异常
- 4.几个建议
- 1)不要生吞异常
- 2)申明具体的异常
- 3)尽可能的捕获具体异常
- 4)永远不要捕获Throwable
- 5)不要丢失异常信息
- 6)日志和上抛不可兼得
- 7)不要在finally里抛异常
- 8)不要为了捕获而捕获
- 9)不要使用printStackTrace()或类似的语句
- 10)不一定要catch
- 11)“Throw early catch late”
- 12)记得用finall善后
- 13)上抛信息明确的异常
- 14)永远不要使用异常来做流程控制
- 15)尽早校验输入
- 16)一条信息打印异常
- 17)让你的异常信息更充实
- 18)如果线程被interrupted一定要结束线程
- 19)使用模板来减少重复的try-catch代码
- 20)文档中加上异常说明
本篇文章主要给大家介绍一些众所周知的异常处理原则,但是也有部分鲜为人知,但也很有用的原则,希望能引发各位对异常处理的思考,以及在开发过程中,写出更优美的代码。
1.异常介绍
大致可以把异常分成三种情况下的异常(不正常情况):
- 代码错误引发的异常:比如数组越界,空指针等。
- 客户端错误调用引发的异常:比如用户名最长只允许32,客户端传了100;方法参数不能为空,客户端传了空等。
- 资源错误引发的异常:比如网络错误,硬盘故障,文件被删等。
2.Java中的异常介绍
无图言屌,下面就给出异常的继承关系图:
主要说说这几个概念:
- Checked exceptions:这种异常在代码层面必须要捕获或者在签名处申明这个异常。这种异常是Java强制你必须捕获,因为这些一般一般是不可避免的,比如:网络,文件系统等不可控因素。
- Unchecked exceptions:这种异常不会强制捕获或者在签名处申明。这类异常一般是由于代码问题产生的,比如:数组越界,空指针等。
- Errors:这类错误,一般是在软件层面不可恢复的。比如:
OutOfMemoryError
,LinkageError
, 还有StackOverflowError
。这种错误一般会是的程序(或者程序的一部分)不可用。针对这类错误,一定要有一个良好的日志习惯,不然很难定位。
3.自定义异常
一般我们想要自定义异常的目的都是为了让异常信息更丰富,比如:输入名称不合法,我们可能希望有一个UsernameInvalidException
。本人在代码中曾经这么干过,一个类似的用法,好处很明显,在我们的内部监控系统中,对异常统计界面可以很清晰的反映出是什么问题,但是也带来一个问题,那就是异常数量很多。
在这里我先摆几个大师的意见吧:
- 不要使用自定义异常:
Java已经给我们提供了很多很多异常,尽量复用这些异常,好处有:减少我们的代码量,也就减少了维护的成本和精力,不至于让代码中出现很多只用过一次或几次的异常,最后异常数量爆炸(这就是我遇到的);使用通用异常,也可以减少别人阅读我们的代码,使用我们的接口时,更轻松,毕竟多一个类我们就需要理解这个类存在的意义。这里给几个经常可以用到的异常:IllegalStateException
UnsupportedOperationException
IllegalArgumentException
NoSuchElementException
NullPointerException
- 如果不得不自定义异常,那就写个通用异常:
如果自己不得不写的话,那就写的详细一下,不要只有个String来传达信息,那完全可以用通用的异常来替代,给个包含详细信息的例子:
public class OutOfRangeException
extends IllegalArgumentException {
private final long value, min, max;
public OutOfRangeException(long value, long min, long max) {
super("Value " + value + " out of range " +
"[" + min + ".." + max + "]");
this.value = value;
this.min = min;
this.max = max;
}
public long getValue() {
return value;
}
public long getMin() {
return min;
}
public long getMax() {
return max;
}
}
4.几个建议
1)不要生吞异常
catch (NoSuchMethodException e) {
return null;
}
这样做会让这个异常信息永远的丢失,你将无法知道这个异常的原因,怎么去解决这个异常,甚至你不知道有这个异常的存在。
2)申明具体的异常
public void foo() throws Exception { //不正确的做法
}
这样除了告诉调用方我可能会有异常之外没有任何其他信息,而事实是我们本可以提供更具体的信息,建议这样做:
public void foo() throws SpecificException1, SpecificException2 { //正确的做法
}
3)尽可能的捕获具体异常
try {
someMethod();
} catch (Exception e) {
LOGGER.error("method has failed", e);
}
这么做的问题是,如果你调用的方法中多了一个新的异常,他本来的目的是希望你处理这个新的异常,可是因为你在这里捕获了所有的异常,你可能会忽略这个提醒,而忘记捕获。
4)永远不要捕获Throwable
这样会捕获本来不该有我们来处理的错误,包括一些我们的代码无法处理的错误。
5)不要丢失异常信息
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information"); //不正确
}
这样做会完全丢失异常信息。
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " + e.getMessage()); //不正确
}
这种做法会丢失堆栈信息,建议:
catch (NoSuchMethodException e) {
throw new MyServiceException("Some information: " , e); //正确
}
6)日志和上抛不可兼得
catch (NoSuchMethodException e) {
LOGGER.error("Some information", e);
throw e;
}
这样会导致一个问题,就是一个异常会有多份日志,因为上层可能也会记一次日志。所以要么上抛,要么记日志,不要都做。
7)不要在finally里抛异常
try {
someMethod(); //Throws exceptionOne
} finally {
cleanUp(); //If finally also threw any exception the exceptionOne will be lost forever
}
这样的问题是,如果finally里也抛异常,就会导致真正的异常信息丢失,你只会收到finally里抛的异常。
8)不要为了捕获而捕获
catch (NoSuchMethodException e) {
throw e; //Avoid this as it doesn't help anything
}
这段代码没有任何有意义,你可以直接上抛。
9)不要使用printStackTrace()或类似的语句
这种输出没有任何意义,而且不确定输出路径,对定位问题没有帮助。
10)不一定要catch
try {
someMethod(); //Method 2
} finally {
cleanUp(); //do cleanup here
}
如果你只是想要finally来做善后,那就只用它就可以了,不要用catch。
11)“Throw early catch late”
这句话我不想翻译,因为我希望你能看到这句话,以后你也会见到这句话的。Throw early catch late。在底层抛异常,在信息足够的时候来捕获并处理。
12)记得用finall善后
比如数据库连接,一定要用finally关闭连接。当然你也可以用try-with-resource的方式。
13)上抛信息明确的异常
如果这个方法是解析文件,那么FileNotFoundException
就比NullPointException
更明确。
14)永远不要使用异常来做流程控制
public void useExceptionsForFlowControl() {
try {
while (true) {
increaseCount();
}
} catch (MaximumCountReachedException ex) {
}
//Continue execution
}
public void increaseCount()
throws MaximumCountReachedException {
if (count >= 5000)
throw new MaximumCountReachedException();
}
算我求你了,不要这么干!
15)尽早校验输入
很多异常都是由不合法的输入引起的,所以尽可能早的校验输入。
16)一条信息打印异常
LOGGER.debug("Using cache sector A");
LOGGER.debug("Using retry sector B");
何必呢?而且这样也容易误导其他人,建议:
LOGGER.debug("Using cache sector A, using retry sector B");
17)让你的异常信息更充实
包括堆栈和其他提示信息。
18)如果线程被interrupted一定要结束线程
while (true) {
try {
Thread.sleep(100000);
} catch (InterruptedException e) {} //Don't do this
doSomethingCool();
}
这段代码很cool,但是一般会interrupt线程,要么是超时了,要么是线程池被关闭了,所以你应该尽可能的去结束线程。
19)使用模板来减少重复的try-catch代码
class DBUtil{
public static void closeConnection(Connection conn){
try{
conn.close();
} catch(Exception ex){
//Log Exception - Cannot close connection
}
}
}
使用这个来减少每次都try一遍。
20)文档中加上异常说明
/**
* This method does something extremely useful ...
*
* @param input
* @throws MyBusinessException if ... happens
*/
public void doSomething(String input) throws MyBusinessException { ... }
前人种树后人乘凉,你可能也可以乘凉。
Java Exception最佳实践(转)的更多相关文章
- Atitit.嵌入式web 服务器 java android最佳实践
Atitit.嵌入式web 服务器 java android最佳实践 1. Android4.4.21 2. 自己的webserver1 3. CyberHTTP for Java cybergar ...
- Java异常处理最佳实践
总结一些Java异常的处理原则 Java异常处理最佳实践 不要忘记关闭资源 在finally里关闭资源 public void readFile() { FileInputStream fileInp ...
- paip.myeclipse7 java webservice 最佳实践o228
paip.myeclipse7 java webservice 最佳实践o228 java的ws实现方案:jax-ws>>xfire ws的测试工具 webservice测试调用工具W ...
- 10个精妙的Java编码最佳实践
这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...
- 最重要的 Java EE 最佳实践
參考:IBM WebSphere 开发人员技术期刊: 最重要的 Java EE 最佳实践 IBM WebSphere 开发人员技术期刊: 最重要的 Java EE 最佳实践 2004 年 IBM® W ...
- 你知道吗?10个精妙的 Java 编码最佳实践
这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...
- Java异常处理最佳实践及陷阱防范
前言 不管在我们的工作还是生活中,总会出现各种“错误”,各种突发的“异常”.无论我们做了多少准备,多少测试,这些异常总会在某个时间点出现,如果处理不当或是不及时,往往还会导致其他新的问题出现.所以我们 ...
- Java开发最佳实践(二) ——《Java开发手册》之"异常处理、MySQL 数据库"
二.异常日志 (一) 异常处理 (二) 日志规约 三.单元测试 四.安全规约 五.MySQL数据库 (一) 建表规约 (二) 索引规约 (三) SQL语句 (四) ORM映射 六.工程结构 七.设计规 ...
- Java开发最佳实践(一) ——《Java开发手册》之"编程规约"
Java开发手册版本更新说明 专有名词解释 一. 编程规约 (一) 命名风格 (二) 常量定义 (三) 代码格式 (四) OOP 规约 (五) 集合处理 (六) 并发处理 (七) 控制语句 (八) 注 ...
- .NET Core学习笔记(7)——Exception最佳实践
1.为什么不要给每个方法都写try catch 为每个方法都编写try catch是错误的做法,理由如下: a.重复嵌套的try catch是无用的,多余的. 这一点非常容易理解,下面的示例代码中,O ...
随机推荐
- 【原创】Ftrace使用及实现机制
Ftrace使用及实现机制 版权声明:本文为本文为博主原创文章,转载请注明出处 https://www.cnblogs.com/wsg1100 如有错误,欢迎指正. 目录 Ftrace使用及实现机制 ...
- MyBatis理论
MyBatis简介 MyBatis是什么? MyBatis是一款优秀的持久层框架,一个ORM(对象关系映射)框架,它支持定制化SQL.存储过程以及高级映射.MyBaits避免了几乎所有JDBC代码和手 ...
- Blazor提取出Razor类库,没有css的class的智能提示
最开始从stackoverflow上找到了答案,有两种办法,但都不太理想 后来自己找了新的办法,其实很简单,把要用的css复制到Razor类库的wwwroot文件夹中,默认是不会复制到引用Razor类 ...
- python excel 07版本转换为03版本
需要安装pywin32模块 pip install pywin32 主程序: import win32com.client as win32 import os.path import glob cl ...
- 关于reids免安装的使用与注意事项
redis是我们现在常用的缓存数据库.可是redis官方网站只提供linux版本,而我们又习惯在windows系统上使用开发工具,这又怎么办呢? 幸好微软官方也提供了windows版本,方便根据实际需 ...
- 【转自知乎】NLP算法面试必备!史上最全!PTMs:NLP预训练模型的全面总结
NLP算法面试必备!史上最全!PTMs:NLP预训练模型的全面总结 预训练模型(Pre-trained Models,PTMs)的出现将NLP带入了一个全新时代.2020年3月18日,邱锡鹏老师发表了 ...
- 规范代码编写风格就用 eslint 和 prettier
eslint 可以用于规范我们的编码,使得项目中的代码风格一致,更利于阅读和维护,而 prettier 可以在当我们代码不符合 eslint 规范是进行部分自动修复. eslint 通过 npm in ...
- 【go笔记】使用标准库flag解析命令行参数
前言 Go语言标准库中提供了一个包flag可以解析命令行参数. 示例代码:文件读取 package main import ( "fmt" "flag" &qu ...
- 从零玩转系列之微信支付实战PC端项目构建+页面基础搭建 | 技术创作特训营第一期
一.前言 欢迎来到本期的博客!在这篇文章中,我们将带您深入了解前端开发领域中的一个热门话题: 如何使用 Vue 3 和 Vite 构建前端项目.随着现代 Web 应用程序的需求不断演进, 选择适当的工 ...
- 解码Transformer:自注意力机制与编解码器机制详述与代码实现
本文全面探讨了Transformer及其衍生模型,深入分析了自注意力机制.编码器和解码器结构,并列举了其编码实现加深理解,最后列出基于Transformer的各类模型如BERT.GPT等.文章旨在深入 ...