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对象的属性
二、异常处理
关键字
- try ---监控可能会出现问题的代码。
- catch ---解决问题的部分。
- finally --- 善后的部分。
- throws ----在方法声明的位置,提醒开发者。
- 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.小结
- 无论try中是否有return,是否有异常,finally都一定会执行。
- 如果try中有异常发生,会执行catch中的句子,try中异常后续的位置的语句不会再被执行
- 当try与finally语句中均有return语句,会忽略try中return。
- try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。