学过异常之后一直没有深入使用过,今天再来复习一下
异常的类型
Throwable是所有异常和错误的父类它的子类有Error和Exception
- Error:错误,由Java虚拟机生成并抛出
- Exception:所有异常类的父类,子类对应各种各样可能出现的异常事件,一般需要用户显式的声明或捕获。
- RuntimeException:Exception的子类,特殊的异常,如被0除、数组下标超范围等,产生频率高、处理麻烦,入股显式的声明或捕获对程序可读性和运行效率影响大。因此交给系统自动监测,用户可不必对其处理。
RuntimeException编译器可以处理但用户如果需要也可用throws/throw、try/catch自行处理,如0做除数
public class TestEx {
public static void main(String[] args) {
try {
new TestEx().m(0);
}
catch(ArithmeticException ae) {
ae.printStackTrace();
System.out.println("出错了");
}
}
void m(int i) throws ArithmeticException{
if(i==0)
throw new ArithmeticException("被除数为0");
}
}
运行结果java.lang.ArithmeticException: 被除数为0 出错了 at TestEx.m(TestEx.java:14) at TestEx.main(TestEx.java:5)
其他的异常在函数中会用throws声明,这类必须处理,可以抛出或用try/catch捕捉,如不处理则编译会报错
import java.io.FileInputStream;
public class TextException {
public static void main(String[] args) {
FileInputStream in = null;
in=new FileInputStream("myfile.txt");
}
}
如代码中in=new FileInputStream("myfile.txt")
在编译时报错,如果在eclipse中编写则会有提示。
捕获和处理
Java中对异常的捕获处理常用try、catch、finally
- try中装入的是可能抛出异常的语句,后面可以跟多个catch,代表可能捕捉多个异常。如果没有产生异常则所有catch代码段被忽略。
- try中语句发生异常后会停止执行并对产生的异常和每个catch相比较找到对应的catch后会执行catch中语句。catch中常用方法有getMessage()、printStackTrace(),前者得到时间信息,后者跟踪异常发生是堆栈中内容。
- finally常用于资源的关闭,在try中资源打开后发生异常执行中断,后面的语句无法执行,资源也就无法关闭,而在finally中统一将资源关闭便可安全的运行。finally中语句是在try/catch中语句运行结束后无论如何都会运行的,哪怕try/catch中有return语句。
我们可以做一个实验
public class TestEx {
public static void main(String[] args) {
try {
System.out.println("这是try");
return;
}
catch(ArithmeticException ae) {
System.out.println("这是catch");
}
finally {
System.out.println("这是finally");
}
}
}
结果如下
这是try
这是finally
可以看见try中打印语句执行后return会结束函数,但在此之前finally中打印语句会执行。
我们再讨论一下finally的执行点,观察下面代码
public class TestEx {
static int x=10;
public static void main(String[] args) {
System.out.println(m());
System.out.println(x);
}
static int m() {
try {
System.out.println("这是try");
return x+=1;
}
catch(ArithmeticException ae) {
System.out.println("这是catch");
}
finally {
System.out.println(x);
System.out.println("这是finally");
x+=1;
}
return x;
}
}
结果如下
这是try
11
这是finally
11
12
可以看到
try中打印语句执行完后执行return x+=1;
但在返回之前必定会执行finally中代码,那么finally在x+=1
之前还是之后。
由finally中对x的打印值为11可知在try中return后的语句执行完成之后才会执行finally中的代码。
在finally中我们将x又加了1;但是在main函数中m的返回结果却是11,而我们打印x的值为12。由此可知在return后的语句执行完毕后return的值已经被确定并保存,finally中的代码无法对其产生影响。
当然,在finally中添加return语句可以提前结束函数的执行。
常使用try、catch、finally是很好的习惯,但有时我们对异常无法处理或者无关紧要时我们可以选择抛出
import java.io.FileInputStream;
import java.io.IOException;
public class TestEx {
public static void main(String[] args) throws IOException{
TestEx te=new TestEx();
te.f();
}
void f() throws IOException{
m();
}
void m() throws IOException{
FileInputStream in = new FileInputStream("myfile.txt");
}
}
但我们不推荐这样做,还是老老实实用try/catch吧。