您的位置:首页 > 编程语言 > Java开发

Java异常机制浅析

2014-05-11 16:59 411 查看
Java异常处理机制类图如下:



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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: