logo

异常

Exception和Error有什么区别?

在Java中, Throwable是所有错误或异常的基类。Throwable又分为ErrorException

  1. Exception: 程序本身可以处理的异常,可以通过catch来进行捕获。Exception又可以分为Checked Exception(受检查异常,必须处理) 和 Unchecked Exception (不受检查异常,可以不处理)
  • CheckedException受检异常:编译器会强制检查并要求处理的异常
  • RuntimeException运⾏时异常:程序运⾏中出现异常,⽐如我们熟悉的空指针、数组下标 越界等等
  1. Error :属于程序无法处理的错误,不建议通过catch捕获 。例如Java虚拟机运行错误(Virtual MachineError)、虚拟机内存不够错误(OutOfMemoryError)、类定义错误(NoClassDefFoundError)

try-catch-finally 如何使用?

  • try块 : 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch块 : 用于处理 try 捕获到的异常。
  • finally 块 : 无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

我们来看看几个常见的题目:

  1. 题目(1)
public class TestReflection2 {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.print("3");
        }
    }
}

结果:31,在 return 前会先执⾏ finally 语句块,所以是先输出 finally ⾥ 的 3,再输出 return 的 1。

  1. 题目(2)
public static void main(String[] args) {
        System.out.println(test());
    }

public static int test() {
    try {
        return 1;
    } catch (Exception e) {
        return 2;
    } finally {
        return 3;
    }

结果: 3。 try在return返回前先执⾏ finally,结果 finally 里不按套路出牌,直接 return 了,⾃然也就⾛不到 try ⾥⾯的 return 了 ,注意实际开发中不能在finally中直接return

  1. 题目(3)
try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception" );
} finally {
    System.out.println("Finally");
}

结果:

Try to do something
Catch Exception
Finally

没有return的话,try -catch-finally 依次执行

  1. 题目(4)
public class TestReflection2 {
    public static void main(String[] args) {
        System.out.println(test1());
    }
    public static int test1() {
        int i = 0;
        try {
            i = 2;
            return i;
        } finally {
            i = 3;
        }
    }

}

结果:2, 在执⾏ finally 之前,JVM 会先将 i 的结果暂存起来,然后 finally 执⾏完毕后,会返 回之前暂存的结果,⽽不是返回 i,所以即使 i 已经被修改为 3,最终返回的还是之前暂存起 来的结果 2

  1. 题目(5)
try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception" );
    // 终止当前正在运行的Java虚拟机
    System.exit(1);
} finally {
    System.out.println("Finally");
}

结果:

ry to do something
Catch Exception

我们可以发现,finally中的代码一般是一定会执行的,除了 2 种特殊情况下,finally块的代码也不会被执行:程序所在的线程死亡、关闭 CPU