Java异常机制浅析

Java异常处理机制类图如下:

Java异常机制浅析_第1张图片

    Thorwable类是所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常,又分别称之为不受检查异常(Unchecked Exception)和强制检查异常(Checked Exception)。

    Error与Exception 

    Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。 这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
    Exception是程序本身可以处理的异常,这种异常分两大类:运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。

    运行时异常和非运行时异常 

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

    非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类,是Checked Exception。从程序语法角度讲是必须进行处 理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常。

代码示例

下面的示例检查除数是否为负数,如果是则抛出异常。

强制检查异常类:

/**
 * 强制检查的异常
 * @author lenovo
 *
 */
class MinusException extends Exception{
	private static final long serialVersionUID = 1L;
	
	private long minus;
	
	/**
	 * 强制检查的异常
	 * @param minus
	 */
	public MinusException(long minus){
		this.minus = minus;
	}
	
	@Override
	public String getMessage() {
		return minus + "为负数,不合法!";
	}
}
不受检查异常类:
/**
 * 不受检查的异常
 * @author lenovo
 *
 */
class MinusRunTimeException extends RuntimeException{
	private static final long serialVersionUID = 1L;
	
	private long minus;
	
	/**
	 * 不受检查的异常
	 * @param minus
	 */
	public MinusRunTimeException(long minus){
		this.minus = minus;
	}
	
	@Override
	public String getMessage() {
		return minus + "为负数,不合法!";
	}
}
运算类:
class Minus{
	
	public double throwException(long a, long b) throws MinusException {
		if (b < 0) {
			throw new MinusException(b);
		}
		return a/b;
	}
	
	public double throwRunTimeException(long a, long b) {
		if (b < 0) {
			throw new MinusRunTimeException(b);
		}
		return a/b;
	}
}
从运算类我们看到: 如果方法内抛出了强制检查的异常,则必须在方法签名中声明抛出的异常(当然也可以用try捕获机制处理),如此,当这个方法被调用时必须进行异常处理;如果方法内抛出了不受检查的异常,则无需在方法签名中声明异常,如此,当这个方法被调用时,可以选择处理异常,也可以选择不处理异常。

测试:

public class Test {
	public static void main(String[] args){
		Minus minus = new Minus();
		//强制检查异常
		try{
			System.out.println(minus.throwException(2, -1));
		} catch (MinusException e) {
			e.printStackTrace();
		} 
		//不处理不受检查异常
		System.out.println(minus.throwRunTimeException(2, -2));
		
		System.out.println("Main end!");
	}
}
输出:
cn.com.exception.MinusException: -1为负数,不合法!
	at cn.com.exception.Minus.throwException(Test.java:25)
	at cn.com.exception.Test.main(Test.java:9)
Exception in thread "main" cn.com.exception.MinusRunTimeException: -2为负数,不合法!
	at cn.com.exception.Minus.throwRunTimeException(Test.java:32)
	at cn.com.exception.Test.main(Test.java:14)
最后一条输出语句没有执行,而倒数第二条语句执行了。

修改测试类,选择捕获不受检查的异常:

public class Test {
	public static void main(String[] args){
		Minus minus = new Minus();
		//强制检查异常
		try{
			System.out.println(minus.throwException(2, -1));
		} catch (MinusException e) {
			e.printStackTrace();
		} 
		//处理不受检查异常
		try{
			System.out.println(minus.throwRunTimeException(2, -2));
		} catch (MinusRunTimeException e) {
			e.printStackTrace();
		}
		
		System.out.println("Main end!");
	}
}
输出:
cn.com.exception.MinusException: -1为负数,不合法!
	at cn.com.exception.Minus.throwException(Test.java:30)
	at cn.com.exception.Test.main(Test.java:9)
cn.com.exception.MinusRunTimeException: -2为负数,不合法!
	at cn.com.exception.Minus.throwRunTimeException(Test.java:37)
	at cn.com.exception.Test.main(Test.java:15)
Main end!

最后一条语句执行了!这说明:当程序抛出异常时,如果我们没有捕获异常,程序不会执行下面的代码(而是跳到外层的catch语句之后开始执行);如果我们捕获了异常,当程序执行完catch里的代码(异常处理程序)后,会继续执行下面的代码,也就是说,如果我们捕获了异常,可以让程序在指定的地方从异常状态恢复到正常状态。

最后说明:所有抛出的异常(要么由虚拟机抛出,要么由程序员抛出)都会被捕捉和处理,要么被程序员捕捉和处理,要么被虚拟机捕捉和处理。

从抛出异常到处理异常(catch语句)之间的代码是不会被执行的。例如,下面的代码:

//处理不受检查异常
		try{
			System.out.println(minus.throwRunTimeException(2, -2));
		} catch (MinusRunTimeException e) {
			e.printStackTrace();
		}
插入一句代码:
//处理不受检查异常
		try{
			System.out.println(minus.throwRunTimeException(2, -2));
			System.out.println("hello");
		} catch (MinusRunTimeException e) {
			e.printStackTrace();
		}
程序并不会输出hello。



你可能感兴趣的:(Java异常机制浅析)