java异常

一.异常概述

1.什么是异常?

异常是程序执行期间发生的问题,它中断了程序的正常流程。异常可以由多种原因引起,比如除数为零、数组越界访问、文件找不到等。在 Java 中,所有异常都是从 Throwable 类派生出来的。

2.检查型异常和非检查型异常

检查型异常(Checked Exception):也称为受检异常,编译器强制要求处理的异常。这类异常通常是由外部环境因素导致的,例如 I/O 错误或数据库连接失败。

非检查型异常(Unchecked Exception):不需要在编译时被显式处理的异常。它们通常是由于程序逻辑错误引起的,如空指针引用或数组越界。

3.Error 和 Exception

Error:表示严重的系统级问题,通常是无法恢复的,如内存不足、虚拟机错误等。应用程序不应该试图捕获 Error,因为这通常意味着应用环境已经不稳定。

Exception:表示程序运行中可能出现的问题,这些问题可能是预料之内的,并且可以通过适当的编码来解决。

4.异常的体系结构

java.lang.Throwable:异常体系的根父类

|---java.lang.Error:错误。Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等 严重情况。 一般不编写针对性的代码进行处理。

|---- StackOverflowError、OutOfMemoryError

|---java.lang.Exception:异常。我们可以编写针对性的代码进行处理。

|----编译时异常:(受检异常)在执行javac.exe命令时,出现的异常。

|----- 类装入异常 (ClassNotFoundException)

|----- 文件未找到异常 (FileNotFoundException)

|----- 输入输出异常 (IOException)

|----运行时异常:(非受检异常)在执行java.exe命令时,出现的异常。

|---- 算术异常 (ArithmeticException) 例如:整数除零

|---- 类转换异常 (ClassCastException)

|---- 数组越界 (java.lang.ArrayIndexOutOfBoundsException) 例如:当对数组的索引值为负数或大于等于数组大小时

|---- “主要”数字格式异常 (NumberFormatException)

|---- 类型不匹配 (InputMismatchException)

|---- 空指针异常 (java.lang.NullPointerException) 例如:调用null对象的实例方法、访问null对象的属性

二、异常处理

关键字

  1. try ---监控可能会出现问题的代码。
  2. catch ---解决问题的部分。
  3. finally --- 善后的部分。
  4. throws ----在方法声明的位置,提醒开发者。
  5. throw ---制造异常的,引起开发者注意。

1.默认异常处理

通常我们不对代码可能出现的异常进行处理,Java就会默认处理我们的异常,如下:

默认会在出现异常的代码处,自动创建一个异常对象:ArithmeticException,异常会从方法中出现的抛给调用者,调用者抛给JVM虚拟机,虚拟机收到异常对象后,先在控制台输出异常栈信息数据,直接从出现异常的地方关闭程序。

2.捕获并处理异常 try-catch 块

try-catch 块是处理异常的基本结构。通过将可能发生异常的代码放在 try 块中,并在 catch 块中捕获并处理异常,可以避免程序因异常而崩溃。

 

示例:

finally 块用于包裹无论是否发生异常都必须执行的代码。通常用于释放资源,如关闭文件、数据库连接等。

3.自定义异常 throw

方法体中,在出现异常的条件下直接throw出异常:执行throw则一定抛出了异常。可以理解为,在编程之前就预想到可能发生的异常。

示例:

4.异常处理 throws

throws:与throw方法不同,throws跟在方法声明后面,扔出使用此方法可能发生(或者在定义可能出现异常的变量的当前类后面throws出异常)的异常。其只是发现异常,而不处理,交给方法的调用者来处理。并且一次可以抛出多个异常。

当一个方法可能会抛出多个异常时,如果为每个方法都加上 try-catch 块,代码会变得冗长且难以维护。这时可以使用 throws 关键字在方法签名上声明异常,然后在调用该方法的地方使用 try-catch 块进行处理。

示例:

在这个例子中,myMethod1() 方法声明了可能会抛出 ArithmeticException 和 NullPointerException 异常。在 main 方法中,我们使用 try-catch 块来处理这些异常,这样代码更加简洁和易于维护。

5.小结

三、分析try-catch-finally执行顺序

1.题目一

try、catch、finally 的基础用法,在 return 前会先执行 finally 语句块,所以会先输出 finally 里的 3,再输出 return 的 1。由于这里try中没有异常发生,因此catch中的return不会执行

2.题目二

在 return 前会先执行 finally 语句块,所以会先输出 finally 里的 3,再输出 catch 中 return 的 2。由于这里try中有异常发生,因此try后续语句不会再执行

3.题目三

try中的return前先执行 finally,结果 finally 直接 return 了,自然也就走不到 try 里面的 return 了。

4.题目四

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

5.小结

  1. 无论try中是否有return,是否有异常,finally都一定会执行。
  2. 如果try中有异常发生,会执行catch中的句子,try中异常后续的位置的语句不会再被执行
  3. 当try与finally语句中均有return语句,会忽略try中return。
  4. try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
posted @ 2025-01-08 15:43  无功  阅读(1)  评论(0编辑  收藏  举报