Java异常处理体系

概述

    先看图

    


 

Exception是所有异常的父类,所以他的子类,除了RuntimeException及其子类,是属于编译时异常(检查异常或者叫非运行时异常)。这种异常必须在代码里被显示的捕获语句包住,否则编译不过,而RuntimeException及其子类表示运行时异常,不强制要求写出显示的捕获代码,但如果没有被捕获到,则线程会被强制中断。

 

Java异常机制是为了把异常处理的代码与正常流程的代码分开,避免程序中出现过多的像传统程序那样的非法值判断语句,以致于扰乱了正常流程

 

编译时异常是Java特有的,了解异常处理流程

 

 

class Test {
	public static void main(String args[]) {
		System.out.println(Test.test());
	}

	@SuppressWarnings("finally")
	public static String test() {
		try {
			System.out.println("try");
			throw new Exception();
		} catch (Exception e) {
			System.out.println("catch");
			return "return";
		} finally {
			System.out.println("finally");
			return "return in finally";
		}
	}
}

 

 

如何处理编译时异常:编译时异常出生的目的--捕获异常,并恢复继续执行程序,这种情况就是在主方案行不通时,用备选方案,而且主方案能否行通不能事先知道,必须执行的时候才能知道,所以在一般情况下,备选方案比主方案要的运行结果要差

 

 

 


Throwable是所有异常和错误的父类,它的两个子类Exception和Error分别代表异常和错误

 

其中Exception又可以分为RuntimeException和非RuntimeException。

RuntimeException也称为unchecked exception(不检查异常),非RuntimeException也称为checked exception(检查异常)

 

下面将详细讲述这些异常之间的区别与联系:

1、Error与Exception

Error(错误)表示运行应用程序中较严重问题, 是程序无法处理的错误。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。比如OutOfMemoryError、ThreadDeath等。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

 

Exception(异常)是应用程序中可能的可预测、可恢复问题。一般大多数异常表示中度到轻度的问题。异常一般是在特定环境下产生的,通常出现在代码的特定方法和操作中。在 EchoInput 类中,当试图调用 readLine 方法时,可能出现 IOException 异常。

 

2、运行时异常和非运行时异常

Exception是程序本身可以处理的异常,这种异常分两大类运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。

 

运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

 

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。

 

从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。

 

如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。

 

unchecked异常:

表示错误,程序的逻辑错误。是RuntimeException的子类,比如IllegalArgumentException, NullPointerException和IllegalStateException。

 

不需要在代码中显式地捕获unchecked异常做处理。

 

继承自java.lang.RuntimeException(而java.lang.RuntimeException继承自java.lang.Exception)。

 

Java中的checked异常需要在代码中显式地通过try-catch捕获或者再抛出,如果不需要对这个异常做处理,可以简地将异常再次抛出,这种异常存在一点不足,很多人习惯在代码中直接写一个空的catch块,这样不但使代码变得有些冗余和“丑陋”,而且给调试带来麻烦,增加了代码维护的难度。所以有人说checked使代码变的冗长,空的catch块也没什么意义,所以checked异常应该从Java标准中去除,像C#中就没有checked异常的概念,C#中不强制显式地捕获异常。

 

Java异常之所以会分为这两种,应该是出于如下考虑:

 

checked异常可以帮助开发人员意识到哪一行有可能会出现异常,因为Java的API已经说明了调用哪些方法可能会抛出异常。如果不做处理编译就不能通过,从某种程度上说,这种做法可以避免程序的一些错误。

 

unChecked异常也称为运行时异常,通常RuntimeException都表示用户无法恢复的异常(不改代码无法恢复),如无法获得数据库连接,不能打开文件等。虽然用户也可以像处理checked异常一样捕获unChecked异常。但是如果调用者并没有去捕获unChecked异常时,编译器并不会强制你那么做。

 

例:比如一个把字符转换为整型数值的代码如下:

java 代码:

    String str = “123”;

    int value = Integer.parseInt(str);

parseInt的方法签名为:

    public static int parseInt(String s) throws NumberFormatException

当传入的参数不能转换成相应的整数时,将会抛出NumberFormatException。因为NumberFormatException扩展于RuntimeException,是unChecked异常。所以调用parseInt方法时无需要try…catch

 

public boolean createNewFile() throws IOException {}

IOException属于检查异常

try... catch

 

checked异常

1、非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。

 

2、从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常

 

3、表示无效,不是程序中可以预测的。比如无效的用户输入,文件不存在,网络或者数据库链接错误。这些都是外在的原因,都不是程序内部可以控制的。

 必须在代码中显式地处理。比如try-catch块处理,或者给所在的方法加上throws说明,将异常抛到调用栈的上一层。

 继承自java.lang.Exception(java.lang.RuntimeException除外)。

 

缺点: checked异常导致了太多的try…catch代码

 

 

选择使用哪种异常?

如果一个异常是可以恢复的,可以被调用者正确处理的,使用checked异常。

在使用unChecked异常时,必须在在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常

如果不能确定时,使用unchecked异常。并详细描述可能会抛出的异常,以让调用者决定是否进行处理。

 

如何记录异常 (http://www.cnblogs.com/elaron/archive/2012/11/12/2766776.html

1、Java异常分为checked异常和unchecked异常

 

  checked异常(需要在代码中try……catch显示捕获)

 

  所有继承java.lang.Exception的异常。是可以在执行过程中恢复的。此类异常不是程序中可以预测的,比如无效的用户输入、文件不存在等。这些都是外在的原因,都不是程序内部可以控制的。

 

  unchecked异常(也叫错误,不需要显示捕获)

 

  所有继承java.lang.RuntimeException的异常。是无法处理的错误。

 

2、异常到底应该在什么位置被记录?

 

  在异常最初产生的位置。

 

  如果是可以处理的异常,则处理之后不做记录。如果是无法处理的异常,则把可以仅仅把它封装成另一种异常并往上抛,不必再把已记录过的异常再记录一次。

 

3、记录异常不属于异常类的行为,记录异常类应该由专门的日志系统去做。

 

4、为系统提供一个异常处理框架,由框架来决定是否记录异常和怎么记录异常,而不是由普通程序员去做。

 

5、对于一个应用程序来说,发生所有异常在用户看来都是应用系统内部的异常。因此应该设计一套应用系统的异常框架,以处理系统运行过程中的所有异常。

 

  可以设计一个应用系统的通用类,如AppException,并且这个异常以及这个异常的子类都是运行应用系统时发生的,因此AppException家族应该继承于RuntimeException,这样系统中所有的其他异常都转移为AppException,当异常发生时,前端统一接收到AppException并做统一的处理。

 

6、通用异常处理框架中需要提供配置信息的支持以及统一的异常处理类和异常日志记录类管理,并允许用户以插件形式扩展自定义的异常处理或日志记录方式。

 

 回顾全文,总结一下Java异常处理的要点:

 

1、 异常是程序运行过程过程出现的错误,在Java中用类来描述,用对象来表示具体的异常。

 

Java将其区分为Error与Exception,Error是程序无力处理的错误,Exception是程序可以处理的错误。

 

异常处理是为了程序的健壮性。

 

2、 Java异常类来自于Java API定义和用户扩展。通过继承Java API异常类可以实现异常的转译。

 

3、 异常能处理就处理,不能处理就抛出,最终没有处理的异常JVM会进行处理。

 

4、 异常可以传播,也可以相互转译,但应该根据需要选择合理的异常转译的方向。

 

附件;java异常体系

 

参考:http://www.cnblogs.com/wjq117/archive/2012/05/07/exception.html

 

参考:  Java异常处理终结篇——如何进行Java异常处理设计

 

参考:Java 应用异常使用简单原则 

 

其他资料参考:http://lavasoft.blog.51cto.com/62575/18920/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值