《Java编程思想》笔记——异常

异常

发现错误的理想时机是在编译阶段

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值存放到操作数栈顶。


持续完善补充!

你可能感兴趣的:(《Java编程思想》笔记——异常)