异常的基本概念
异常(Exception)是程序在运行时发生的、不正常的或意外的状况,它打断了程序的正常执行流程。在编程中,异常用于处理错误情况,使得程序能够以一种优雅的方式响应错误,而不是简单地崩溃或终止执行。
异常的定义
在Java等编程语言中,异常被定义为一种特殊的对象,它是Throwable
类或其子类的实例。当程序中出现错误情况时,Java虚拟机(JVM)会创建一个表示该错误的异常对象,并将其抛出(throw)。程序的其余部分可以通过捕获(catch)这个异常对象来响应错误,并执行相应的错误处理代码。
异常的分类
Java中的异常主要分为两大类:检查型异常(Checked Exceptions)和非检查型异常(Unchecked Exceptions)。此外,还有一种特殊的错误(Errors),它也被视为异常的一种,但通常不由程序直接处理。
- 检查型异常(Checked Exceptions):
- 这些异常在编译时就被检查。如果方法可能抛出检查型异常,但方法本身没有处理这些异常(即没有try-catch块或没有在方法签名中声明throws),那么编译器会报错。
- 检查型异常通常是由外部因素导致的,如文件I/O错误、网络问题或SQL异常等。
- 常见的检查型异常包括
IOException
、SQLException
等。
- 非检查型异常(Unchecked Exceptions):
- 这些异常在编译时不会被检查。如果方法抛出了非检查型异常,那么调用者可以选择捕获这些异常,也可以选择不捕获。
- 非检查型异常通常是由程序逻辑错误或运行时问题导致的,如空指针异常(
NullPointerException
)、数组越界异常(ArrayIndexOutOfBoundsException
)等。 - 非检查型异常包括运行时异常(
RuntimeException
及其子类)和错误(Error
及其子类)。
- 错误(Errors):
- 错误也是
Throwable
的子类,但它通常表示更严重的问题,如JVM内部错误、资源耗尽等。 - 错误很少由程序直接处理,因为大多数错误都是致命的,无法恢复。
- 常见的错误包括
OutOfMemoryError
、StackOverflowError
等
- 错误也是
异常处理的关键字
- try:用于包裹可能抛出异常的代码块。try块中的代码会被监视,一旦发生异常,就会跳转到相应的catch块进行处理。
- catch:用于捕获和处理异常。catch块跟在try块之后,用于捕获指定类型的异常,并对其进行处理。可以有多个catch块用于捕获不同类型的异常。
- finally:用于定义无论是否发生异常都要执行的代码块。finally块必定会被执行,通常用于释放资源或进行清理工作。
- throw:用于主动抛出异常。可以在代码中使用throw关键字抛出自定义异常对象或Java内置的异常对象。
- throws:用于声明方法可能抛出的异常。在方法声明中可以使用throws关键字声明方法可能抛出的异常类型,让调用者知晓需要处理的异常。
Java异常处理流程
1. 异常的产生
- 当Java程序执行过程中遇到错误或异常情况时,会生成一个对应的异常对象。这个异常对象包含了异常的类型和异常发生时的相关信息。
2. 异常的抛出
- 异常对象一旦生成,就会被抛出。抛出异常的过程是自动的,由Java虚拟机(JVM)或程序中的throw语句完成。
- 如果是在JVM中自动抛出的异常(如数组越界、空指针引用等),则不需要程序员显式编写throw语句。
- 如果是程序员想要主动抛出异常,可以使用throw语句抛出一个自定义或Java内置的异常对象。
3. 异常的捕获
- 异常的捕获是通过try-catch语句实现的。try块中包含了可能产生异常的代码。
- 当try块中的代码执行时,如果发生了异常,JVM会查找与之匹配的catch块。
- 如果有匹配的catch块,则执行该catch块中的代码来处理异常。如果没有匹配的catch块,则异常会继续向上传播。
4. 异常的处理
- 在catch块中,可以对捕获到的异常进行处理。处理方式包括但不限于:
- 记录错误日志,以便后续分析。
- 向用户显示错误信息,提示用户发生了错误。
- 尝试恢复操作,使程序能够继续执行。
- 抛出新的异常,将当前异常封装为新的异常类型,并继续向上传播。
5. finally块的执行
- finally块是可选的,但它提供了一个在try-catch结构结束时执行的代码块。
- 无论try块中的代码是否抛出异常,finally块中的代码都会被执行。这通常用于释放资源,如关闭文件、数据库连接等。
- 如果try块或catch块中有return语句,finally块仍然会执行,但return语句会在finally块执行完毕后才执行。
6. 异常的传递
- 如果在当前方法中无法处理某个异常,可以使用throws关键字将该异常传递给调用者。
- 调用者可以在自己的try-catch块中处理该异常,或者继续向上传递。
- 如果异常一直传递到main方法仍未被捕获,则程序会终止执行,并显示异常信息。
7. 自定义异常
- Java允许开发者定义自己的异常类,以表示特定的错误情况。
- 自定义异常类通常继承自
Exception
或RuntimeException
类,并可以根据需要添加额外的属性和方法。 - 通过使用自定义异常,开发者可以更精确地描述程序中可能出现的错误情况,并提供更清晰的错误信息。
示例
Java异常处理流程是通过try
、catch
和finally
(以及可选的throw
和throws
)语句来实现的。当Java程序在执行过程中遇到异常情况时,它会立即停止当前的操作,并寻找最近的异常处理程序(即catch
块)。如果找到了合适的处理程序,则程序将控制权转移到该处理程序;如果没有找到,则异常会被传播到上一层调用者,这个过程会一直继续,直到找到合适的处理程序或者达到程序的顶层(通常是main
方法),如果仍然没有被处理,则程序会终止,并可能打印出堆栈跟踪信息。
以下是Java异常处理流程的示例:
public class ExceptionHandlingExample {
// 假设这个方法可能会抛出异常
public static void potentiallyDangerousMethod() throws Exception {
// 这里只是一个示例,实际上这里并不会抛出异常
// 但为了演示,我们假设在某个条件下会抛出异常
boolean somethingWentWrong = true; // 假设某个条件触发了异常
if (somethingWentWrong) {
throw new Exception("Something went wrong!");
}
}
public static void main(String[] args) {
try {
// 调用可能会抛出异常的方法
potentiallyDangerousMethod();
// 如果potentiallyDangerousMethod()正常执行完毕,没有抛出异常
// 则以下代码将执行
System.out.println("No exception was thrown.");
} catch (Exception e) {
// 如果potentiallyDangerousMethod()抛出了异常
// 则控制流将跳转到这里
System.err.println("An exception occurred: " + e.getMessage());
// 在这里,你可以对异常进行处理,比如记录日志、恢复操作等
// 你也可以选择重新抛出异常,让上一层调用者处理
// throw e; // 取消注释以重新抛出异常
} finally {
// 无论是否发生异常,finally块中的代码都会执行
// 它是用于清理资源的,比如关闭文件、数据库连接等
System.out.println("This code runs whether an exception occurs or not.");
}
// 程序继续执行,即使前面有异常发生(除非异常被重新抛出并传播到更高层)
System.out.println("Main method continues to execute.");
}
}
在这个示例中
-
potentiallyDangerousMethod
方法可能会抛出一个Exception
(为了演示,我们假设在某个条件下会抛出)。 -
在
main
方法中,我们调用了potentiallyDangerousMethod
,并且将其放在了try
块中。 -
如果
potentiallyDangerousMethod
正常执行,则try
块中的后续代码(在potentiallyDangerousMethod
调用之后的打印语句)将执行。 -
如果
potentiallyDangerousMethod
抛出了异常,则try
块中的剩余代码将被跳过,控制流将跳转到与异常类型相匹配的catch
块。在这个例子中,我们捕获了Exception
类型的异常,所以任何从potentiallyDangerousMethod
抛出的Exception
(或其子类)都将被这个catch
块捕获。 -
在
catch
块中,我们打印了异常信息,并可以选择对异常进行处理(比如记录日志、执行恢复操作等)。在这个例子中,我们简单地打印了异常消息。 -
无论是否发生异常,
finally
块中的代码都会执行。它通常用于执行清理操作,比如关闭文件流、数据库连接等。 -
如果
catch
块中没有重新抛出异常,则程序将继续执行finally
块之后的代码。如果catch
块中重新抛出了异常,则异常处理流程将再次开始,寻找新的catch
块来处理这个重新抛出的异常。
finally
块是可选的,但在某些情况下(比如需要确保资源被释放时)它是非常重要的。另外,如果在try
块或catch
块中使用了return
语句,则finally
块仍然会执行。但是,请注意finally
块中的代码不能阻止return
语句的执行或改变其返回值(尽管可以通过抛出异常来做到这一点)。
结束
标签:Java,抛出,介绍,try,finally,catch,异常 From: https://blog.csdn.net/qq_68874993/article/details/141468731