Java 中的 try-catch-finally
与 try-with-resource
文章目录
〇、其他相关博客
Java异常详解
https://blog.csdn.net/qq_29689343/article/details/95736854
一、try-catch-finally 捕获和处理异常
1、概述
简介
try-catch-finally
是最基本的异常处理机制。它由三个关键字组成:try
、catch
和finally
。代码块放在try
块中,如果在执行该块时抛出了异常,就会跳转到catch
块中进行异常处理。finally
块中的代码始终都会被执行,无论是否有异常发生。
try
块后可跟零个、一个或多个catch
块,如果没有catch
块,则必须跟一个finally
块。
finally
执行机制
无论是否捕获到异常,finally
块大都会被执行!
有不会被执行到的可能:
- 如果在try或catch块中出现了System.exit()方法,JVM会立即终止程序,导致finally块不被执行。
- 如果在执行到finally块之前,JVM发生了内部错误或系统崩溃,那么finally块也将不会被执行。
- 如果程序所运行的线程被强制终止(如使用Thread.stop()方法),那么finally块也可能不会被执行。
- 如果try或catch块中发生了无限循环,那么finally块将永远无法被执行。
2、代码格式
try {
// 可能抛出异常的代码
// ...
} catch (ExceptionType1 e1) {
// 处理 ExceptionType1 异常
// ...
} catch (ExceptionType2 e2) {
// 处理 ExceptionType2 异常
// ...
} finally {
// 在任何情况下都会执行的代码
// ...
}
3、最佳实践
- 在try块中包含可能会抛出异常的代码。将可能引发异常的代码放在try块中,以便能够捕获和处理异常。
- 在catch块中捕获并处理异常。在catch块中,您可以指定要处理的异常类型,并提供异常处理程序。这可以确保程序在出现异常时不会崩溃,而是能够继续执行。
- 不要忽略异常。在处理异常时,不要将异常抛出到方法调用者中,而是应该使用合适的异常处理程序来处理异常。这样可以使代码更加健壮和可靠。
- 使用多个catch块。如果代码可能抛出多种类型的异常,可以使用多个catch块来捕获和处理每种类型的异常。这样可以更好地控制异常处理过程,并确保代码能够正确处理每种类型的异常。
- 在finally块中释放资源。在finally块中,您可以指定要在代码执行完毕后执行的代码。这通常用于释放资源,例如关闭文件或网络连接等。无论代码是否抛出异常,finally块中的代码都会得到执行。
- 尽量使用局部变量。在try块中使用局部变量可以减少异常的影响范围,使得代码更容易理解和维护。
- 避免在finally块中抛出异常。如果在finally块中抛出异常,可能会导致代码变得更加复杂和难以理解。因此,应该在finally块中避免抛出异常,而是使用合适的异常处理程序来处理异常。
- 谨慎使用
return
语句:在try
块、catch
块和finally
块中使用return
语句时要小心,确保逻辑正确并符合预期。finally
块中的return
语句可能会覆盖try
块或catch
块中的return
语句。
二、try-with-resources 自动关闭资源
1、概述
try-with-resources
是从Java 7开始引入的一种异常处理机制。它用于自动关闭实现了 java.lang.AutoCloseable
接口或 java.io.Closeable
的资源,如文件或网络连接,以确保它们正确地关闭,即使在发生异常时也能被关闭。
使用try-with-resources
时,我们可以在try
语句中声明一个或多个资源,并在代码块结束后自动关闭这些资源。资源的声明和初始化以分号分隔。
2、代码示例
try (ResourceType1 resource1 = new ResourceType1(); ResourceType2 resource2 = new ResourceType2()) {
// 使用 resource1 和 resource2 的代码
// ...
} catch (ExceptionType e) {
// 处理异常
// ...
}
在上述示例中,ResourceType1
和 ResourceType2
是实现了AutoCloseable
接口的资源类型。它们在try
块中声明和初始化,并在代码块结束后自动关闭。如果发生异常,程序将跳转到相应的catch
块进行异常处理,并且在那之前,资源会被自动关闭。
3、try-with-resources 中 try catch finally 三个代码块
在try-with-resources
语句中,可以包含try
块、catch
块和finally
块,它们的含义和作用**与传统的try-catch-finally
块相同。**下面对它们进行详细解释:
try
块:try
块包含需要进行异常处理的代码。在try
块中,我们可以声明和初始化一个或多个资源对象,这些资源对象必须实现AutoCloseable
接口或其子接口Closeable
。try
块中的代码在执行完毕后,无论是否发生异常,都会自动关闭这些资源。catch
块:catch
块用于捕获并处理try
块中抛出的异常。它可以包含一个或多个catch
子句,每个子句用于处理特定类型的异常。当在try
块中的代码发生异常时,程序会跳转到匹配的catch
块中,执行相应的异常处理代码。finally
块:finally
块中的代码在try
块中的代码执行完毕后,无论是否发生异常,都会被执行。它通常用于执行一些必要的收尾操作,如释放资源、清理临时数据等。即使在try
块或catch
块中使用了return
语句,finally
块中的代码也会被执行。
代码示例
try (ResourceType resource = new ResourceType()) {
// 可能抛出异常的代码
// ...
} catch (ExceptionType e) {
// 处理特定类型的异常
// ...
} finally {
// 在任何情况下都会执行的代码
// ...
}
可以只有 try
块!
4、关闭资源
在try-with-resources
中,无论是否发生异常,资源都会被正确关闭。即使在try
块中发生异常,也会执行资源的关闭操作。
当try-with-resources
语句执行完毕时,会自动调用每个资源对象的close()
方法来关闭资源。这是通过编译器生成的字节码来实现的,确保资源的正确关闭。
如果在try
块中发生异常,控制流会立即跳转到catch
块或终止程序,但在跳转之前,编译器会调用每个资源对象的close()
方法,确保它们被正确关闭。
这是try-with-resources
相较于传统的try-catch-finally
块的一个重要优势,它能够确保资源的自动关闭,无论是否发生异常。这样可以避免资源泄漏,并简化资源管理的代码。
5、最佳实践
- 使用
try-with-resources
来管理资源:对于需要手动关闭的资源,如文件、数据库连接等,尽量使用try-with-resources
来自动管理资源的关闭。这样可以确保资源在使用完毕后被正确地关闭,避免资源泄漏。 - 实现
AutoCloseable
接口:要使用try-with-resources
,资源类必须实现AutoCloseable
接口或其子接口Closeable
。这两个接口定义了close()
方法,用于释放资源。确保资源类正确实现了这些接口。 - 只声明和初始化必要的资源:在
try-with-resources
语句中,只声明和初始化需要使用的资源。避免声明不必要的资源,以保持代码的清晰和简洁。 - 多个资源的处理:可以在
try
语句中声明和初始化多个资源,它们会按照声明的顺序依次关闭。每个资源的声明和初始化之间使用分号分隔。 - 资源的顺序:对于有依赖关系的资源,应按照正确的顺序声明和初始化它们,以确保依赖的资源在使用后能正确关闭。
- 异常处理:如果在
try
块中的代码抛出异常,try-with-resources
会自动关闭已声明的资源,然后抛出最后一个异常。可以使用catch
块捕获和处理该异常,或者将异常继续传递给上层调用者。 - 嵌套的
try-with-resources
:可以在一个try-with-resources
语句中嵌套另一个try-with-resources
语句。确保内部的资源在外部资源之前声明,以确保正确的关闭顺序。 - 使用合适的资源类型:选择适合的资源类型,这取决于资源的性质和需求。Java标准库中提供了许多实现了
AutoCloseable
接口的资源类,如FileInputStream
、Socket
等。也可以自定义实现AutoCloseable
接口的资源类。