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】 异常与自定义异常的更多相关文章

  1. java基础之异常 · fossi

    在开发中,异常处理是一个不可绕开的话题,我们对于异常的处理已经非常熟练了,对于异常本身的概念.用法等不再赘述了,直接结合面试问题来加深对异常的理解吧. Throwable 可以用来表示任何可以作为异常 ...

  2. Java基础之异常

    1.异常的概念 异常:程序在运行时出现的不正常情况,也可以说是出现的问题: Java中的异常:出现的不正常的问题也是一类事物,这类事物有一些共性的东西,比如有名称,有产生的原因等,将这些共性的部分抽取 ...

  3. Java面向对象之异常(自定义异常)

    一.基础概念 在自定义的程序中,如果有了问题.也可以像java中的异常一样,对问题进行描述. 注意:1.继承RuntimeException的异常,不需要进行处理.在执行过程中有异常会直接抛出. 2. ...

  4. 【java基础之异常】死了都要try,不淋漓尽致地catch我不痛快!

    目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...

  5. 【java基础之异常】死了都要try

    目录 1.异常 1.1 异常概念 1.2 异常体系 1.3 异常分类 1.4 异常的产生过程解析 2. 异常的处理 2.1 抛出异常throw 2.2 Objects非空判断 2.3 声明异常thro ...

  6. Java基础笔记-异常

    Java中的异常机制: Throwable类是 Java 语言中所有错误或异常的超类.主要包括两个子类: Error和Exception. 一般中要处理的异常是Exception. Java中最常见的 ...

  7. 黑马程序员----java基础:异常

    dff ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 经常写程序的人对try...catch...finally语句肯定是不陌生的了.但是好多 ...

  8. java基础(21):异常

    1. 异常 什么是异常?Java代码在运行时期发生的问题就是异常. 在Java中,把异常信息封装成了一个类.当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置.原因等). 1.1 ...

  9. JAVA基础知识|异常

    一.基础知识 处理异常,java提供了一个优秀的解决方案:异常处理机制. java把异常当作对象来处理,所有的异常都是由Throwable继承而来,但在下一层立即分解为两个分支:Error和Excep ...

  10. java基础之异常。

    异常: (1)异常:异常就是Java程序在运行过程中出现的错误. 异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象.其实就是Java对不正常情况进行描述后 ...

随机推荐

  1. DB操作-用批处理执行Sql语句

    用批处理在命令行状态下调用查询分析器来执行这个sql文件里的语句.下面就是sqlserver帮助里对于查询分析器(isqlw)命令行参数的解释:isqlw 实用工具(SQL 查询分析器)使您得以输入 ...

  2. canvas简单下雨特效

    前面做了两个简单的效果,这次就来个下雨的效果 思路简单的说一下 随机在屏幕中的位置画雨滴,moveTo(x,y) 雨滴的长度就是lineTo(x,y+len) 每次重新绘制页面,就能达到下雨的效果了 ...

  3. [NOI2012]骑行川藏(未完成)

    题解: 满分又是拉格朗日啥的 以后再学 自己对于n=2猜了个三分 然后对拍了一下发现是对的

  4. day8--socketserver回顾

    sockeserver主要实现多并发的情况,我们知道,socket只能一对一用户进行交互,如何实现一对多交互,socketserver就是用来解决这个问题的. socketserver--共有这么几种 ...

  5. python全栈开发day28-网络编程之粘包、解决粘包,上传和下载的作业

    一.昨日内容回顾 1. tcp和udp编码 2. 自定义mysocket解决编码问题 二.今日内容总结 1.粘包 1)产生粘包原因: (1).接收方不知道消息之间的边界,不知道一次性要取多少字节的数据 ...

  6. 汇编之 eax, ebx, ecx, edx, esi, edi, ebp, esp??

    一般寄存器:AX.BX.CX.DXAX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器 索引暂存器:SI.DISI:来源索引暂存器,DI:目的索引暂存器 堆叠.基底暂存器:SP.BP ...

  7. 目标检测——IoU 计算

    Iou 的计算 我们先考虑一维的情况:令 \(A = [x_1,x_2], B = [y_1, y_2]\),若想要 \(A\) 与 \(B\) 有交集,需要满足如下情况: 简言之,要保证 \(A\) ...

  8. 免费的ASP.NET空间和SQLServer2008 Express

      Login Register Web Hosting Support Forum Ask Experts Articles ASP.NET 4.5 & SQL 2012 Hosting P ...

  9. 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)

    To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...

  10. Java并发程序设计(九)设计模式与并发之不变模式

    设计模式与并发之不变模式 使用不变模式的目的:除去多线程中的同步操作,提高并行程序的性能. 一个类在的内部状态创建后,在整个生命周期内都不会发生改变,该类就是不变类. /** * @author: T ...