java⽤异常判断_深⼊理解java异常处理机制
1. 引⼦
try…catch…finally恐怕是⼤家再熟悉不过的语句了,⽽且感觉⽤起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲⾃体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。不信?那你看看下⾯的代码,“猜猜”它执⾏后的结果会是什么?不要往后看答案、也不许执⾏代码看真正答案哦。如果你的答案是正确,那么这篇⽂章你就不⽤浪费时间看啦。
package Test;
public class TestException {
public TestException() {
}
boolean testEx() throws Exception {
boolean ret = true;
try {
ret = testEx1();
} catch (Exception e) {
System.out.println("testEx, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx, finally; return value=" + ret);
return ret;
}
}
boolean testEx1() throws Exception {
boolean ret = true;
try {
ret = testEx2();
if (!ret) {
return false;
try catch的使用方法}
System.out.println("testEx1, at the end of try");
return ret;
} catch (Exception e) {
System.out.println("testEx1, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx1, finally; return value=" + ret); return ret;
}
}
boolean testEx2() throws Exception {
boolean ret = true;
try {
int b = 12;
int c;
for (int i = 2; i >= -2; i--) {
c = b / i;
System.out.println("i=" + i);
}
return true;
} catch (Exception e) {
System.out.println("testEx2, catch exception");
ret = false;
throw e;
} finally {
System.out.println("testEx2, finally; return value=" + ret); return ret;
}
}
public static void main(String[] args) {
TestException testException1 = new TestException();
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
你的答案是什么?是下⾯的答案吗?
i=2
i=1
testEx2, catch exception
testEx2, finally; return value=false
testEx1, catch exception
testEx1, finally; return value=false
testEx, catch exception
testEx, finally; return value=false
如果你的答案真的如上⾯所说,那么你错啦。^_^,那就建议你仔细看⼀看这篇⽂章或者拿上⾯的代码按各种不同的情况修改、执⾏、测试,你会发现有很多事情不是原来想象中的那么简单的。现在公布正确答案:
i=2
i=1
testEx2, catch exception
testEx2, finally; return value=false
testEx1, finally; return value=false
testEx, finally; return value=false
2.JAVA异常
异常指不期⽽⾄的各种状况,如:⽂件不到、⽹络连接失败、⾮法参数等。异常是⼀个事件,它发⽣在程序运⾏期间,⼲扰了正常的指令流程。Java通 过API中Throwable类的众多⼦类描述各种不同的异常。因⽽,Java异常都是对象,是Throwable⼦类的实例,描述了出现在⼀段编码中的 错误条件。当条件⽣成时,错误将引发异常。
Java异常类层次结构图:
图1 Java异常类层次结构图
在 Java 中,所有的异常都有⼀个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可⽤异常传播机制通过 Java 应⽤程序传输的任何问题的共性。
Throwable: 有两个重要的⼦类:Exception(异常)和 Error(错误),⼆者都是 Java 异常处理的重要⼦类,各⾃都包含⼤量⼦类。
Error(错误):是程序⽆法处理的错误,表⽰运⾏应⽤程序中较严重问题。⼤多数错误与代码编写者执⾏的操作⽆关,⽽表⽰代码运⾏时
JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运⾏错误(Virtual MachineError),当 JVM 不再有继续执⾏操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发⽣时,Java虚拟机(JVM)⼀般会选择线程终⽌。
。这些错误表⽰故障发⽣于虚拟机⾃⾝、或者发⽣在虚拟机试图执⾏应⽤时,如Java虚拟机运⾏错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应⽤程序的控制和处理能⼒之 外,⽽且绝⼤多数是程序运⾏时不允许出现的状况。对于设计合理的应⽤程序来说,即使确实发⽣了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的⼦类描述。
Exception(异常):是程序本⾝可以处理的异常。
Exception 类有⼀个重要的⼦类 RuntimeException。RuntimeException 类及其⼦类表⽰“JVM 常⽤操作”引发的错误。例如,若试图使⽤空值对象引⽤、除数为零或数组越界,则分别引发运⾏时异常(NullPointerException、ArithmeticException)和ArrayIndexOutOfBoundException。
注意:异常和错误的区别:异常能被程序本⾝可以处理,错误是⽆法处理。
通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。
可查异常(编译器要求必须处置的异常):正确的程序在运⾏中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在⼀定程度上它的发⽣是可以预计的,⽽且⼀旦发⽣这种异常状况,就必须采取某种⽅式进⾏处理。
除了RuntimeException及其⼦类以外,其他的Exception类及其⼦类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么⽤try-catch语句捕获它,要么⽤throws⼦句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运⾏时异常(RuntimeException与其⼦类)和错误(Erro
r)。
Exception 这种异常分两⼤类运⾏时异常和⾮运⾏时异常(编译异常)。程序中应当尽可能去处理这些异常。
运⾏时异常:都是RuntimeException类及其⼦类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常⼀般是由程序逻辑错误引起的,程序应该从逻辑⾓度尽可能避免这类异常的发⽣。
运⾏时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有⽤try-catch语句捕获它,也没有⽤throws ⼦句声明抛出它,也会编译通过。
⾮运⾏时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其⼦类。从程序语法⾓度讲是必须进⾏处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及⽤户⾃定义的Exception异常,⼀般情况下不⾃定义检查异常。
4.处理异常机制
在 Java 应⽤程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常:当⼀个⽅法出现错误引发异常时,⽅法创建异常对象并交付运⾏时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运⾏时系统负责寻处置异常的代码并执⾏。
捕获异常:在⽅法抛出异常之后,运⾏时系统将转为寻合适的异常处理器(exception handler)。潜在的异常处理器是异常发⽣时依次存留在调⽤栈中的⽅法的集合。当异常处理器所能处理的异常类型与⽅法抛出的异常类型相符时,即为合适 的异常处理器。运⾏时系统从发⽣异常的⽅法开始,依次回查调⽤栈中的⽅法,直⾄到含有合适异常处理器的⽅法并执⾏。当运⾏时系统遍历调⽤栈⽽未到合适 的异常处理器,则运⾏时系统终⽌。同时,意味着Java程序的终⽌。
对于运⾏时异常、错误或可查异常,Java技术所要求的异常处理⽅式有所不同。
由于运⾏时异常的不可查性,为了更合理、更容易地实现应⽤程序,Java规定,运⾏时异常将由Java运⾏时系统⾃动抛出,允许应⽤程序忽略运⾏时异常。
对于⽅法运⾏中可能出现的Error,当运⾏⽅法不欲捕捉时,Java允许该⽅法不做任何抛出声明。因为,⼤多数Error异常属于永远不能被允许发⽣的状况,也属于合理的应⽤程序不该捕捉的异常。
对于所有的可查异常,Java规定:⼀个⽅法必须捕捉,或者声明抛出⽅法之外。也就是说,当⼀个⽅法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的⽅法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于⾃⾝语句所引发并抛出的异常,也可能是由某个调⽤的⽅法或者Java运⾏时 系统等抛出的异常。也就是说,⼀个⽅法所能捕捉的异常,⼀定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
任何Java代码都可以抛出异常,如:⾃⼰编写的代码、来⾃Java开发环境包中代码,或者Java运⾏时系统。⽆论是谁,都可以通过Java的throw语句抛出异常。
从⽅法中抛出的任何异常都必须使⽤throws⼦句。
捕捉异常通过try-catch语句或者try-catch-finally语句实现。
总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
4.1 捕获异常:try、catch 和 finally
<-catch语句
在Java中,异常通过try-catch语句捕获。其⼀般语法形式为:
try {
// 可能会发⽣异常的程序代码
} catch (Type1 id1){
// 捕获并处置try抛出的异常类型Type1
}
catch (Type2 id2){
//捕获并处置try抛出的异常类型Type2
}
关键词try后的⼀对⼤括号将⼀块可能发⽣异常的代码包起来,称为监控区域。Java⽅法在运⾏过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由Java运⾏时系统试图寻匹配的catch⼦句以捕获异常。若有匹配的catch⼦句,则运⾏其异常处理代码,try-catch语句结束。
匹配的原则是:如果抛出的异常对象属于catch⼦句的异常类,或者属于该异常类的⼦类,则认为⽣成
的异常对象与catch块捕获的异常类型相匹配。
例1 捕捉throw语句抛出的“除数为0”异常。
public class TestException {
public static void main(String[] args) {
int a = 6;
int b = 0;
try { // try监控区域
if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常
System.out.println("a/b的值是:" + a / b);
}
catch (ArithmeticException e) { // catch捕捉异常
System.out.println("程序出现异常,变量b不能为0。");
}
System.out.println("程序正常结束。");
}
}
运⾏结果:程序出现异常,变量b不能为0。
程序正常结束。
例1 在try监控区域通过if语句进⾏判断,当“除数为0”的错误条件成⽴时引发ArithmeticException异常,创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运⾏时系统,由系统寻匹配的异常处理器catch并运⾏相应异 常处理代码,打印输出“程序出现异常,变量b不能为0。”try-catch语句结束,继续程序流程。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论