海内存知己,天涯若比邻。
王勃·《送杜少府之任蜀州》
一、异常
程序编译阶段可以发现一些语法上的错误,比如“使用中文符号”等。然而,编译期间并不能发现所有的错误,剩下的这些错误就必须在运行期间解决,比如“除数为0”。Java使用异常机制处理程序运行期间发生的不可预知的错误,异常是指阻止当前方法或作用域继续执行的问题,当发生异常时,程序会从当前运行环境跳出,并将该异常交至上一级环境(例如当被调函数方式异常时,会将异常交至主调函数)。
当在程序运行期间发生异常时,会做以下处理:
- 使用new创建一个异常对象(Java万物皆对象,异常也不例外);
- 当前执行代码被终止;
- 异常处理机制开始寻找异常处理程序,然后开始执行异常处理程序。
异常也是一种对象,所有标准异常类都有两个构造器:
(Exception类是所有异常类的父类)
一个是默认构造器 :new Exception()
一个是接受字符串作为参数:new Exception(“messages……”)
(异常对象通常仅包含异常类型,除此之外不包含其他任何有意义的内容)
二、 try、catch、finally
- try块用于捕获异常;
- catch子句紧跟在try块之后, catch子句接受且仅接受一个异常类型标识符,异常被抛出后,会匹配与异常类型相匹配的第一个catch子句;
- finally子句是一个可选语句,跟在最后一个catch子句后面,无论try块中是否抛出异常,finally子句中的语句都会得到执行(即使catch语句中含有return语句)。
public class Test {
private int fun() {
try {//捕获异常
for (int i = 5; ; i--) {//可能抛出异常的语句
System.out.println(10 / i);//该for循环不存在语法错误,但当i为0时,将会产生一个除0的运行时错误
}
} catch (Exception e) {//可以填入具体的错误类型,若无法预知将要发生的错误类型,可直接使用Exception,该类是所有异常类的父类
System.out.println(e);
return 0;
} finally {//无论是否抛出异常,该子句都会执行
System.out.println("finally子句被调用");
}
}
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.fun());
}
}
运行结果:
三、 抛异常throw
throw用于将异常向上抛出,上一级可以选择处理异常或者继续将异常向上抛。
public class Test {
private void fun1() throws Exception {
throw new Exception("异常");
}
private void fun2() throws Exception {
try {
fun1();
} catch (Exception e) {//将fun1中抛出的异常继续向上抛
throw e;
}
}
public static void main(String[] args) {
Test test = new Test();
try {//处理抛出的异常
test.fun2();
} catch (Exception e) {
System.out.println(e);
}
}
}
运行结果:
四、 栈轨迹
通过getStackTrace方法可以获得一个由栈轨迹中的元素所组成的数组,下标为0的元素是栈顶元素并且是最后一个方法调用,其他方法调用依次往后排列。
public class Test {
private void fun1() throws Exception {
throw new Exception("异常");
}
private void fun2() throws Exception {
try {
fun1();
} catch (Exception e) {//将fun1中抛出的异常继续向上抛
throw e;
}
}
public static void main(String[] args) {
Test test = new Test();
try {//处理抛出的异常
test.fun2();
} catch (Exception e) {
for (StackTraceElement ste : e.getStackTrace())
System.out.println(ste);
}
}
}
运行结果: