异常
发现错误的理想时机是在编译阶段
Throwable这个Java类被用来表示任何可以作为异常被抛出的类。Throwable对象可分为两类:
- Error用来表示编译时和系统错误;
- Exception是可以被抛出的基本类型。
Java中异常处理的常用结构如下:
public static int testFinally() {
try {
System.out.println("try");
return testReturn1();
} catch (Exception e) {
System.out.println("catch");
e.getStackTrace(); // 该方法返回一个由栈轨迹中的元素所构成的数组
e.printStackTrace(); // 该方法将上面方法返回的数组输出
return 2;
} finally {
System.out.println("finally");
return testReturn3();
}
// return 4; // Error: Unreachable code
}
public static int testReturn1() {
System.out.println("return1");
return 1;
}
public static int testReturn3() {
System.out.println("return3");
return 3;
}
// 该方法返回值为:3
- 无论try块中的异常是否抛出,finally子句都能得到执行,但是finally子句在某些场景下并不能得到执行(多线程中断等)。
- 异常处理系统会按照代码的书写顺序找出“最近”的处理程序。
- 若在catch子句中不处理异常,则异常就像丢失了一样。
- RuntimeException被称为“不受检查异常”,这种异常输出错误,将被自动捕获。
下面探究一下finally与return的执行顺序
public static void main(String[] args) {
System.out.println(testFinally());
}
public static int testFinally() {
try {
System.out.println("try");
return testReturn1();
} catch (Exception e) {
System.out.println("catch");
return 2;
} finally {
System.out.println("finally");
return testReturn3();
}
// return 4; // Error: Unreachable code
}
public static int testReturn1() {
System.out.println("return1");
return 1;
}
public static int testReturn3() {
System.out.println("return3");
return 3;
}
///
try
return1
finally
return3
3
从这个输出可以看出,try块中的return会执行,但是最终的返回值却是3,也就是finally里面返回的那个值。那么问题来了,try块的return的值去哪里了?
public static void main(String[] args) {
System.out.println(testFinally());
}
private static int n = 1;
public static int testFinally() {
try {
return n;
} catch (Exception e) {
return 2;
} finally {
n = 3;
}
}
///
1
上面的测试就是猜想,若是try块中的return值并不会返回,那么我特意在finally中改变n的值,期望最终的返回值为修改后的3,但是结果确实修改前的1.
最终猜想执行顺序:
1. 执行:try的return,结果保存在操作数栈顶;
2. 执行:操作数栈顶值(try的return值)复制到局部变量区作为返回值;
3. 执行:finally语句块中的代码;
4. 执行:将第2步复制到局部变量区的返回值又复制回操作数栈顶;
5. 执行:return指令,返回操作数栈顶的值;
若finally中有return操作,则第4步就会把finally的return值存放到操作数栈顶。
持续完善补充!
网友评论