关于说说异常(Exception)的详细解释和常见问题,你能告诉我吗?

2026-04-19 07:312阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1854个文字,预计阅读时间需要8分钟。

关于说说异常(Exception)的详细解释和常见问题,你能告诉我吗?

Java的异常处理,面试不再怕被问到!Java中的异常都是`Throwable`的子类,它包含两个子类:`Exception`和`Error`。程序本身可以捕获并处理`Exception`类型的异常。`Exception`又分为两类:运行时异常(`RuntimeException`)和非运行时异常(`Exception`的其他子类)。

两万字详解Java异常,面试再也不怕被问到! (qq.com)

Java的异常都是Throwable的子类,他包含两个子类

  1. 程序本身可以捕获并且可以处理的异常。Exception 这种异常又分为两类:运行时异常和编译时异常。
    • RuntimeException 类及其子类,Java 编译器不会检查它。属于非受检异常。当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。比如NullPointerException空指针异常、ArrayIndexOutBoundException数组下标越界异常、ClassCastException类型转换异常、ArithmeticExecption算术异常。
    • 编译时异常,Exception 中除 RuntimeException 及其子类之外的异常。属于受检查异常。要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。比如 IO相关的异常,ClassNotFoundException(没有找到指定的类异常),SQLException。
  2. Error类及其子类,代表程序中无法处理的错误,表示运行应用过程中出现了严重的错误。一般是JVM出现问题。这些错误是非受检异常,非代码性错误,此类错误发生时,应用程序不应该去处理。我们不应该实现任何新的Error子类。eg. Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如 OutOfMemoryError:内存不足错误;StackOverflowError:栈溢出错误。

追问:什么是受检查异常什么是非受检异常?

受检异常:编译器要求必须处理的异常。除 RuntimeException 及其子类外,其他的 Exception 异常都属于受检异常。

非受检异常:编译器不会进行检查并且不要求必须处理的异常,包括运行时异常(RuntimeException极其子类)和错误(Error)。

关于说说异常(Exception)的详细解释和常见问题,你能告诉我吗?

追问:throw和throws的区别是什么?

throw关键字用在方法内部,只能用于抛出一种异常。用来抛出方法或者代码块中的异常,受检查异常和非受检异常都可以被抛出。

throws关键字用在方法声明上,可以抛出多个异常,用来表示该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常。

追问:JVM是如何处理异常的?

在一个方法中发生异常的话,这个方法会创建一个异常对象,并转交给JVM,该异常对象包含异常名称、异常描述以及异常发生时应用程序的状态。创建异常对象并转交给JVM的过程称为抛出异常。

可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做调用栈。

JVM会顺着调用栈会查找是否有可以处理异常的代码,如果有,则调用异常处理代码。当JVM发现可以处理异常的代码时,会把发生的异常传递给他。如果JVM没有找到可以处理该异常的代码块,就会将该异常转交给默认的异常处理器,默认异常处理器打印异常信息并终止应用程序。

追问:try-catch-finally 如何使用?

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

追问:下面代码输出?

public static void main(String[] args) { System.out.println(f(2)); } public static int f(int value) { try { return value * value; } finally { if (value == 2) { return 0; } } }

输出0,

当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。

追问:try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

public static int getInt() { int a = 10; try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; /* * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返回路径就形成了 * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40 * 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30 */ } finally { a = 40; } return a; } // 执行结果:30

public static int getInt() { int a = 10; try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; } finally { a = 40; //如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直接返回40 return a; } } // 执行结果:40

会执行,在 return 前执行。

在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值,然后如果在 finally 中修改了返回值,就会返回修改后的值。

追问:finally 中的代码什么情况下不会执行?

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

输出:

Try to do something Catch Exception -> RuntimeException

以下情况finally 中的代码不会执行。

  1. 虚拟机终止运行
  2. 程序所在的线程死亡。
  3. 关闭 CPU。

追问:知道try-with-resources

为了实现资源的自动释放,要求使用的类实现了AutoCloseable接口。

private static void tryWithResourceTest(){ try (Scanner scanner = new Scanner(new FileInputStream("c:/abc"),"UTF-8")){ // code } catch (IOException e){ // handle exception } }

try 代码块退出时,会自动调用 scanner.close 方法,和把 scanner.close 方法放在 finally 代码块中不同的是,若 scanner.close 抛出异常,则会被抑制,抛出的仍然为原始异常。

本文共计1854个文字,预计阅读时间需要8分钟。

关于说说异常(Exception)的详细解释和常见问题,你能告诉我吗?

Java的异常处理,面试不再怕被问到!Java中的异常都是`Throwable`的子类,它包含两个子类:`Exception`和`Error`。程序本身可以捕获并处理`Exception`类型的异常。`Exception`又分为两类:运行时异常(`RuntimeException`)和非运行时异常(`Exception`的其他子类)。

两万字详解Java异常,面试再也不怕被问到! (qq.com)

Java的异常都是Throwable的子类,他包含两个子类

  1. 程序本身可以捕获并且可以处理的异常。Exception 这种异常又分为两类:运行时异常和编译时异常。
    • RuntimeException 类及其子类,Java 编译器不会检查它。属于非受检异常。当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。比如NullPointerException空指针异常、ArrayIndexOutBoundException数组下标越界异常、ClassCastException类型转换异常、ArithmeticExecption算术异常。
    • 编译时异常,Exception 中除 RuntimeException 及其子类之外的异常。属于受检查异常。要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。比如 IO相关的异常,ClassNotFoundException(没有找到指定的类异常),SQLException。
  2. Error类及其子类,代表程序中无法处理的错误,表示运行应用过程中出现了严重的错误。一般是JVM出现问题。这些错误是非受检异常,非代码性错误,此类错误发生时,应用程序不应该去处理。我们不应该实现任何新的Error子类。eg. Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如 OutOfMemoryError:内存不足错误;StackOverflowError:栈溢出错误。

追问:什么是受检查异常什么是非受检异常?

受检异常:编译器要求必须处理的异常。除 RuntimeException 及其子类外,其他的 Exception 异常都属于受检异常。

非受检异常:编译器不会进行检查并且不要求必须处理的异常,包括运行时异常(RuntimeException极其子类)和错误(Error)。

关于说说异常(Exception)的详细解释和常见问题,你能告诉我吗?

追问:throw和throws的区别是什么?

throw关键字用在方法内部,只能用于抛出一种异常。用来抛出方法或者代码块中的异常,受检查异常和非受检异常都可以被抛出。

throws关键字用在方法声明上,可以抛出多个异常,用来表示该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常。

追问:JVM是如何处理异常的?

在一个方法中发生异常的话,这个方法会创建一个异常对象,并转交给JVM,该异常对象包含异常名称、异常描述以及异常发生时应用程序的状态。创建异常对象并转交给JVM的过程称为抛出异常。

可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做调用栈。

JVM会顺着调用栈会查找是否有可以处理异常的代码,如果有,则调用异常处理代码。当JVM发现可以处理异常的代码时,会把发生的异常传递给他。如果JVM没有找到可以处理该异常的代码块,就会将该异常转交给默认的异常处理器,默认异常处理器打印异常信息并终止应用程序。

追问:try-catch-finally 如何使用?

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

追问:下面代码输出?

public static void main(String[] args) { System.out.println(f(2)); } public static int f(int value) { try { return value * value; } finally { if (value == 2) { return 0; } } }

输出0,

当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。

追问:try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

public static int getInt() { int a = 10; try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; /* * return a 在程序执行到这一步的时候,这里不是return a 而是 return 30;这个返回路径就形成了 * 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40 * 再次回到以前的路径,继续走return 30,形成返回路径之后,这里的a就不是a变量了,而是常量30 */ } finally { a = 40; } return a; } // 执行结果:30

public static int getInt() { int a = 10; try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; } finally { a = 40; //如果这样,就又重新形成了一条返回路径,由于只能通过1个return返回,所以这里直接返回40 return a; } } // 执行结果:40

会执行,在 return 前执行。

在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值,然后如果在 finally 中修改了返回值,就会返回修改后的值。

追问:finally 中的代码什么情况下不会执行?

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

输出:

Try to do something Catch Exception -> RuntimeException

以下情况finally 中的代码不会执行。

  1. 虚拟机终止运行
  2. 程序所在的线程死亡。
  3. 关闭 CPU。

追问:知道try-with-resources

为了实现资源的自动释放,要求使用的类实现了AutoCloseable接口。

private static void tryWithResourceTest(){ try (Scanner scanner = new Scanner(new FileInputStream("c:/abc"),"UTF-8")){ // code } catch (IOException e){ // handle exception } }

try 代码块退出时,会自动调用 scanner.close 方法,和把 scanner.close 方法放在 finally 代码块中不同的是,若 scanner.close 抛出异常,则会被抑制,抛出的仍然为原始异常。