关于处理异常中finally的面试题
- 首先明确什么是异常?
异常是在程序中导致程序中断运行的一种指令流。
比如最常举例的被除数除以除数,若除数为零,则出错。
一般当程序运行时,如果出现异常,则会中断执行。该过程包括:
1.JVM将会创建一个异常类对象,该对象包含异常信息。
2.main方法未对该异常进行处理时,自动将异常抛给main的执行者JVM。
3.JVM对异常信息进行响应(将异常信息显示到控制台,中断处理。)
int arr[] = new int[3];
int b = arr[3];
出现了数组索引越界的异常。
- 使用try、catch方法进行异常处理
//如果要想对异常进行处理,则必须采用标准的处理格式,处理格式语法如下:
try{
// 有可能发生异常的代码段
}catch(异常类型1 对象名1){
// 异常的处理操作
}catch(异常类型2 对象名2){
// 异常的处理操作
}finally{
// 异常的统一出口
}
try+catch的处理流程
1、 一旦产生异常,则系统会自动产生一个异常类的实例化对象。
2、 那么,此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异常抛出。
3、 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。
-
finally
在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码。 -
异常的体系结构
异常指的是Exception , Exception类, 在Java中存在一个父类Throwable(可能的抛出)
Throwable存在两个子类:
1.Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。
2.Exception:一般表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。
当存在finally代码块的执行时,表示不管程序产生异常与否,都要进行该语句块的执行。
package day05;
public class Demo2 {
public static void main(String[] args) {
Person p = haha();
System.out.println(p.age);
}
static class Person {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static Person haha() {
Person p = new Person();
try {
p.age = 18;
return p;
}catch (Exception e) {
return null;
}finally {
p.age = 28;
}
}
}
程序运行结果是28,这表明执行返回p对象的时候,在这之前还对p的age值进行了修改。这就是finally的作用。
接着我们来看下面的代码:
package day05;
public class Demo3 {
public static void main(String[] args) {
int a = haha();
System.out.println(a);
}
public static int haha() {
int a = 10;
try {
return 10;
}catch (Exception e) {
return 0;
}finally {
a = 28;
}
}
}
为什么这里的输出会是10呢?
原因在于haha()函数返回a的数据的时候,已经将a备份了一次,在finally执行之后也是不会修改a的值的。而为什么之前的age又可以被修改呢?
这是因为try中当数据返回之前都会进行备份,而备份引用数据类型和基本数据类型是有区别的,引用数据类型备份的是堆内存中的地址值。
此时返回的还是p所指向的地址,而执行完finally代码块后,对象的age值变为了28,改变了其内容。所以结果也跟着改变了。
用图理解:
还有一个可以避免执行finally代码块的方法就是:
当catch中出现退出程序时,finally就不能被执行了!
如果有错误,希望可以被大家指出改正,谢谢!