Java 基础【17】 异常与自定义异常
1.异常的分类
Throwable 是所有异常类的基类,它包括两个子类:Exception 和 Error。
a. 错误 (Error)
错误是无法难通过程序来解决的,所以程序不应该抛出这种类型的对象。
如果出现了这样的内部错误,除了通知给用户,并尽力使程序安全地终止。当然这类情况是很少出现的(上图 OutOfMemoryError)。
a.非运行时异常(UnChecked Exception)
Java 中凡是继承自 Exception 但不是继承自 RuntimeException 的类都是非运行时异常(上图 NoSuchMethodException)。
UnChecked 与 Check 指编译器是否进行检查,是否提示强制 try catch。
b.运行时异常(Runtime Exception)
RuntimeException 类直接继承自 Exception 类,称为运行时异常。
Java 中所有的运行时异常都直接或间接的继承自 RuntimeException (上图 NullPointerException)。
2.异常的处理
a.对应非运行时异常,必须对其进行处理。处理方式有两种:
- 使用 try…catch…finally 语句块进行捕获
- 在产生异常的方法所在的方法声明 throws Exception
b.对于运行时异常,可以不对其进行处理,也可以对其进行处理。一般情况下都不对其进行处理。
在使用Java API的方法时会产生异常,由于实际的需要,我们需要创建和使用自定义异常。使用全新的异常类,应用到系统程序中。
3.自定义异常
在介绍自定义异常时,首要先谈谈什么要使用自定义异常,使用自定义异常的好处。
创建自定义异常是为了表示应用程序的一些错误类型,为代码可能发生的一个或多个问题提供新的含义;
可以显示代码多个位置之间的错误的相似处,也可区分代码运行时可能出现的相似问题的一个或多个错误,或给出应用程序中一组错误的特殊含义。
服务器的基本作用是处理与客户机的通信,若使用标准Java API 使编写的代码在多个位置抛出 IOException。
在设置服务器、等待客户机连接和获取通讯流时,可抛出 IOException。
在通信期间及试图断开连接时,也会抛出IOException。
简而言之,服务器的各个部分都是引发 IOException,但对于服务器而言,这样 IOException 意义不尽相同。
虽然由同一异常类型表示,但与各个异常先关的业务含义存在差异,报告和恢复操作也不相同。
所以,可以将一个异常与服务器配置、启动问题关联,将另一个异常与客户机通讯的实际行动关联,将第三个异常与服务器关闭任务关联等。
为此,我们需要使用自定义异常来定为问题,定位问题与异常实际准确的位置。
自定义异常类可以继承 Throwable 类或者 Exception 类,自定义异常类之间也可以有继承关系。
需要为自定义异常类设计构造方法,以方便构造自定义异常对象。
在继承任何异常时,将自动继承 Throwable 类的一些标准特性,如:错误消息/栈跟踪/ 异常包装....
若要在异常中添加附加信息,则可以为类添加一些变量和方法。
a.首先继承异常类 Exception
本例演示的自定义异常没有按照业务类型来命名,而是创建一个通用异常类。
以 retCd 来区别发生异常的业务类型与发生位置,当然对于具体的 retCd 值,事先必须有具体的规定或说明。
/**
* 多数情况下,创建自定义异常需要继承Exception,本例继承Exception的子类RuntimeException
*/
public class CustomerException extends RuntimeException { private String retCd; //异常对应的返回码
private String msgDes; //异常对应的描述信息 public CustomerException() {
super();
} public CustomerException(String message) {
super(message);
msgDes = message;
} public CustomerException(String retCd, String msgDes) {
super();
this.retCd = retCd;
this.msgDes = msgDes;
} public String getRetCd() {
return retCd;
} public String getMsgDes() {
return msgDes;
}
}
b. 其次声明方法抛出自定义异常
为了使用自定义异常,必须通知调用代码的类:要准备处理这个异常类型。
为此,声明一个或多个方法抛出异常。找到异常发生点,新建异常并加上关键字 throw。
public class TestClass { public void testException() throws CustomerException {
try {
//..some code that throws CustomerException } catch (Exception e) {
throw new CustomerException("14000001", "String[]strs 's length < 4");
}
}
}
c.捕获异常之后的操作
public class TestCustomerException { public static void main(String[] args) {
try {
TestClass testClass = new TestClass();
testClass.testException();
} catch (CustomerException e) {
e.printStackTrace();
System.out.println(e.getMsgDes());
System.out.println(e.getRetCd());
}
}
}
4.最佳实践
a.记得释放资源
如果你正在用数据库或网络连接的资源,要记得释放它们。
如果你使用的 API 仅仅使用 unchecked exception,你应该用完后释放它们,使用 try-final。
public void dataAccessCode() {
try {
Connection conn = getConnection(); //do some code that throws SQLException } catch (SQLException ex) {
ex.printStacktrace();
} finally {
closeConnection(conn);
}
} public static void closeConnection(Connection conn) {
try {
conn.close();
} catch (SQLException ex) {
logger.error("Cannot close connection");
throw new RuntimeException(ex);
}
}
在这个例子中,finally 关闭了连接,如果关闭过程中有问题发生的话,会抛出一个 RuntimeException。
b.不要使用异常控制流程
生成栈回溯是非常昂贵的,栈回溯的价值是在于调试。
在流程控制中,栈回溯是应该避免的,因为客户端仅仅想知道如何继续。
下面的代码,一个自定义的异常 MaximumCountReachedException,用来控制流程。
public void useExceptionsForFlowControl() {
try {
while (true) {
increaseCount();
}
} catch (MaximumCountReachedException ex) {
}
//Continue execution
} public void increaseCount() throws MaximumCountReachedException {
if (count >= 5000)
throw new MaximumCountReachedException();
}
useExceptionsForFlowControl()使用了一个无限的循环来递增计数器,直至异常被抛出。
这样写不仅降低了代码的可读性,而且代码效率低下。
c. 不要忽略异常
当一个 API 方法抛出 checked exception 时,它是要试图告诉你需要采取某些行动处理它。
如果它对你来说没什么意义,不要犹豫,直接转换成 unchecked exception 抛出,千万不要仅仅用空的 {}catch 它,然后当没事发生一样忽略它。
d. 不要 catch 最高层次的 exception
Unchecked exception 是继承自 RuntimeException 类的,而 RuntimeException 继承自 Exception。如果 catch Exception 的话,你也会 catch RuntimeException。
try{
..
}catch(Exception ex){}
上面的代码会忽略掉 unchecked exception。
e. 仅记录 exception 一次
对同一个错误的栈回溯(stack trace)记录多次的话,会让程序员搞不清楚错误的原始来源。所以仅仅记录一次就够了。
总结:这里是我总结出的一些异常处理最佳实施方法。我并不想引起关于 checked exception 和 unchecked exception 的激烈争论。
你可以根据你的需要来设计代码。我相信,随着时间的推移,你会找到些更好的异常处理的方法的。
Java 基础【17】 异常与自定义异常的更多相关文章
- java基础之异常 · fossi
在开发中,异常处理是一个不可绕开的话题,我们对于异常的处理已经非常熟练了,对于异常本身的概念.用法等不再赘述了,直接结合面试问题来加深对异常的理解吧. Throwable 可以用来表示任何可以作为异常 ...
- Java基础之异常
1.异常的概念 异常:程序在运行时出现的不正常情况,也可以说是出现的问题: Java中的异常:出现的不正常的问题也是一类事物,这类事物有一些共性的东西,比如有名称,有产生的原因等,将这些共性的部分抽取 ...
- Java面向对象之异常(自定义异常)
一.基础概念 在自定义的程序中,如果有了问题.也可以像java中的异常一样,对问题进行描述. 注意:1.继承RuntimeException的异常,不需要进行处理.在执行过程中有异常会直接抛出. 2. ...
- 【java基础之异常】死了都要try,不淋漓尽致地catch我不痛快!
目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...
- 【java基础之异常】死了都要try
目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...
- Java基础笔记-异常
Java中的异常机制: Throwable类是 Java 语言中所有错误或异常的超类.主要包括两个子类: Error和Exception. 一般中要处理的异常是Exception. Java中最常见的 ...
- 黑马程序员----java基础:异常
dff ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 经常写程序的人对try...catch...finally语句肯定是不陌生的了.但是好多 ...
- java基础(21):异常
1. 异常 什么是异常?Java代码在运行时期发生的问题就是异常. 在Java中,把异常信息封装成了一个类.当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置.原因等). 1.1 ...
- JAVA基础知识|异常
一.基础知识 处理异常,java提供了一个优秀的解决方案:异常处理机制. java把异常当作对象来处理,所有的异常都是由Throwable继承而来,但在下一层立即分解为两个分支:Error和Excep ...
- java基础之异常。
异常: (1)异常:异常就是Java程序在运行过程中出现的错误. 异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象.其实就是Java对不正常情况进行描述后 ...
随机推荐
- IntelliJ IDEA 下的SVN使用
最近公司的很多同事开始使用IntelliJ Idea,便尝试了一下,虽然快捷键与eclipse 有些不同,但是强大的搜索功能与“漂亮的界面”(个人认为没有eclipse好看 ),还是值得我们去使用的. ...
- python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))
昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...
- 步步为营-17-FileStream-文件加密/解密
以前使用的File是操作小的文本文件,用的并不常见,FileStream(操作字节),可以操作所有格式的文件,用途较广泛 下面做一个通过文件流给文件加密解密的小软件. using System; us ...
- poj 3233 S = A + A^2 + A^3 + … + A^k A是一个n X n矩阵 (矩阵快速幂)
S = A + A^2 + A^3 + … + A^k A是一个n*n矩阵 Sample Input 2 2 4 //n k MOD0 11 1Sample Output 1 22 3 先求 I + ...
- mysql 不区分大小写的解决
mysql查询默认是不区分大小写的 如: select * from some_table where str=‘abc';select * from some_table where str='AB ...
- bzoj1026
题意: windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 数据范围 A,B≤ ...
- P3144 关闭农场 并查集 反向
FJ和他的奶牛们正在计划离开小镇做一次长的旅行,同时FJ想临时地关掉他的农场以节省一些金钱. 这个农场一共有被用M条双向道路连接的N个谷仓(1<=N,M<=3000).为了关闭整个农场,F ...
- Ubuntu 初始配置
1)在修改source.list前,最好先备份一份 sudo cp /etc/apt/sources.list /etc/apt/sources.list_backu2. 2)执行命令打开sour ...
- 化学1(chem1)- 化学合成
P2784 化学1(chem1)- 化学合成 还是spfa,距离数组初始化为-1,松弛操作改为*就好了,一开始老是超时,后来加了一个visit数组就过了,这个重复造成的效率浪费还是蛮大的,以后都要加. ...
- C++雾中风景12:聊聊C++中的Mutex,以及拯救生产力的Boost
笔者近期在工作之中编程实现一个Cache结构的封装,需要使用到C++之中的互斥量Mutex,于是花了一些时间进行了调研.(结果对C++标准库很是绝望....)最终还是通过利用了Boost库的share ...