@@ -1226,77 +1226,135 @@ JDK 提供了很多内置的注解(比如 `@Override` 、`@Deprecated`),
1226
1226
1227
1227
## 异常
1228
1228
1229
- ### Java 异常类层次结构图
1229
+ ** Java 异常类层次结构图概览** :
1230
+
1231
+ ![ types-of-exceptions-in-java] ( /Users/guide/Documents/GitHub/JavaGuide/docs/java/basis/images/types-of-exceptions-in-java.png )
1230
1232
1231
- ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-12/Java%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%E5%9B%BE.png )
1232
1233
1233
- <p style =" font-size :13px ;text-align :right " >图片来自:https://simplesnippets.tech/exception-handling-in-java-part-1/</p >
1234
1234
1235
1235
![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-12/Java%E5%BC%82%E5%B8%B8%E7%B1%BB%E5%B1%82%E6%AC%A1%E7%BB%93%E6%9E%84%E5%9B%BE2.png )
1236
1236
1237
1237
<p style =" font-size :13px ;text-align :right " >图片来自:https://chercher.tech/java-programming/exceptions-java</p >
1238
1238
1239
- 在 Java 中,所有的异常都有一个共同的祖先 ` java.lang ` 包中的 ` Throwable ` 类。 ` Throwable ` 类有两个重要的子类 ` Exception ` (异常)和 ` Error ` (错误)。 ` Exception ` 能被程序本身处理( ` try-catch ` ), ` Error ` 是无法处理的(只能尽量避免)。
1239
+ ### Exception 和 Error 有什么区别?
1240
1240
1241
- ` Exception ` 和 ` Error ` 二者都是 Java 异常处理的重要子类,各自都包含大量子类。
1241
+ 在 Java 中,所有的异常都有一个共同的祖先 ` java.lang ` 包中的 ` Throwable ` 类。 ` Throwable ` 类有两个重要的子类:
1242
1242
1243
- - ** ` Exception ` ** :程序本身可以处理的异常,可以通过 ` catch ` 来进行捕获。` Exception ` 又可以分为 受检查异常( 必须处理) 和 不受检查异常( 可以不处理)。
1244
- - ** ` Error ` ** :` Error ` 属于程序无法处理的错误 ,我们没办法通过 ` catch ` 来进行捕获 。例如,Java 虚拟机运行错误(` Virtual MachineError ` )、虚拟机内存不够错误(` OutOfMemoryError ` )、类定义错误(` NoClassDefFoundError ` )等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
1243
+ - ** ` Exception ` ** :程序本身可以处理的异常,可以通过 ` catch ` 来进行捕获。` Exception ` 又可以分为 Checked Exception (受检查异常, 必须处理) 和 Unchecked Exception (不受检查异常, 可以不处理)。
1244
+ - ** ` Error ` ** :` Error ` 属于程序无法处理的错误 ,我们没办法通过 ` catch ` 来进行捕获 。例如Java 虚拟机运行错误(` Virtual MachineError ` )、虚拟机内存不够错误(` OutOfMemoryError ` )、类定义错误(` NoClassDefFoundError ` )等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
1245
1245
1246
- ** 受检查异常 **
1246
+ ### Checked Exception 和 Unchecked Exception 有什么区别?
1247
1247
1248
- Java 代码在编译过程中,如果受检查异常没有被 ` catch ` /` throw ` 处理的话,就没办法通过编译 。比如下面这段 IO 操作的代码 。
1248
+ ** Checked Exception ** 即受检查异常, Java 代码在编译过程中,如果受检查异常没有被 ` catch ` /` throw ` 处理的话,就没办法通过编译 。
1249
1249
1250
- ![ check-exception ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-12/check-exception.png )
1250
+ 比如下面这段 IO 操作的代码:
1251
1251
1252
- 除了 ` RuntimeException ` 及其子类以外,其他的 ` Exception ` 类及其子类都属于受检查异常 。常见的受检查异常有: IO 相关的异常、 ` ClassNotFoundException ` 、 ` SQLException ` ...。
1252
+ ![ ] ( ./images/checked-exception.png )
1253
1253
1254
- ** 不受检查异常 **
1254
+ 除了 ` RuntimeException ` 及其子类以外,其他的 ` Exception ` 类及其子类都属于受检查异常 。常见的受检查异常有: IO 相关的异常、 ` ClassNotFoundException ` 、 ` SQLException ` ...。
1255
1255
1256
- Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。
1256
+ ** Unchecked Exception ** 即 ** 不受检查异常 ** , Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。
1257
1257
1258
1258
` RuntimeException ` 及其子类都统称为非受检查异常,例如:` NullPointerException ` 、` NumberFormatException ` (字符串转换为数字)、` ArrayIndexOutOfBoundsException ` (数组越界)、` ClassCastException ` (类型转换错误)、` ArithmeticException ` (算术错误)等。
1259
1259
1260
- ### Throwable 类常用方法
1260
+ ![ ] ( ./images/unchecked-exception.png )
1261
1261
1262
- - ** ` public String getMessage() ` ** :返回异常发生时的简要描述
1263
- - ** ` public String toString() ` ** :返回异常发生时的详细信息
1264
- - ** ` public String getLocalizedMessage() ` ** :返回异常对象的本地化信息。使用 ` Throwable ` 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 ` getMessage() ` 返回的结果相同
1265
- - ** ` public void printStackTrace() ` ** :在控制台上打印 ` Throwable ` 对象封装的异常信息
1262
+ ### Throwable 类常用方法有哪些?
1266
1263
1267
- ### try-catch-finally
1264
+ - ` String getMessage() ` : 返回异常发生时的简要描述
1265
+ - ` String toString() ` : 返回异常发生时的详细信息
1266
+ - ` String getLocalizedMessage() ` : 返回异常对象的本地化信息。使用 ` Throwable ` 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 ` getMessage() ` 返回的结果相同
1267
+ - ` void printStackTrace() ` : 在控制台上打印 ` Throwable ` 对象封装的异常信息
1268
+
1269
+ ### try-catch-finally 如何使用?
1268
1270
1269
1271
- ** ` try ` 块:** 用于捕获异常。其后可接零个或多个 ` catch ` 块,如果没有 ` catch ` 块,则必须跟一个 ` finally ` 块。
1270
1272
- ** ` catch ` 块:** 用于处理 try 捕获到的异常。
1271
1273
- ** ` finally ` 块:** 无论是否捕获或处理异常,` finally ` 块里的语句都会被执行。当在 ` try ` 块或 ` catch ` 块中遇到 ` return ` 语句时,` finally ` 语句块将在方法返回之前被执行。
1272
1274
1273
- ** 在以下 3 种特殊情况下, ` finally ` 块不会被执行: **
1275
+ 示例:
1274
1276
1275
- 1 . 在 ` try ` 或 ` finally ` 块中用了 ` System.exit(int) ` 退出程序。但是,如果 ` System.exit(int) ` 在异常语句之后,` finally ` 还是会被执行
1276
- 2 . 程序所在的线程死亡。
1277
- 3 . 关闭 CPU。
1277
+ ``` java
1278
+ try {
1279
+ System . out. println(" Try to do something" );
1280
+ throw new RuntimeException (" RuntimeException" );
1281
+ } catch (Exception e) {
1282
+ System . out. println(" Catch Exception -> " + e. getMessage());
1283
+ } finally {
1284
+ System . out. println(" Finally" );
1285
+ }
1286
+ ```
1278
1287
1279
- 下面这部分内容来自 issue: < https://github.com/Snailclimb/JavaGuide/issues/190 > 。
1288
+ 输出:
1280
1289
1281
- ** 注意:** 当 try 语句和 finally 语句中都有 return 语句时,在方法返回之前,finally 语句的内容将被执行,并且 finally 语句的返回值将会覆盖原始的返回值。如下:
1290
+ ```
1291
+ Try to do something
1292
+ Catch Exception -> RuntimeException
1293
+ Finally
1294
+ ```
1295
+
1296
+ ** 注意:不要在 finally 语句块中使用 return!** 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句不会被执行。
1297
+
1298
+ 示例:
1282
1299
1283
1300
``` java
1284
- public class Test {
1285
- public static int f (int value ) {
1286
- try {
1287
- return value * value;
1288
- } finally {
1289
- if (value == 2 ) {
1290
- return 0 ;
1291
- }
1301
+ public static void main(String [] args) {
1302
+ System . out. println(f(2 ));;
1303
+ }
1304
+
1305
+ public static int f(int value) {
1306
+ try {
1307
+ return value * value;
1308
+ } finally {
1309
+ if (value == 2 ) {
1310
+ return 0 ;
1292
1311
}
1293
1312
}
1294
1313
}
1295
1314
```
1296
1315
1297
- 如果调用 ` f(2) ` ,返回值将是 0,因为 finally 语句的返回值覆盖了 try 语句块的返回值。
1316
+ 输出:
1317
+
1318
+ ```
1319
+ 0
1320
+ ```
1321
+
1322
+ ### finally 中的代码一定会执行吗?
1323
+
1324
+ 不一定的!在某些情况下,finally 中的代码不会被执行。
1325
+
1326
+ 就比如说 ` finally ` 之前虚拟机被终止运行的话,finally 中的代码就不会被执行。
1327
+
1328
+ ``` java
1329
+ try {
1330
+ System . out. println(" Try to do something" );
1331
+ throw new RuntimeException (" RuntimeException" );
1332
+ } catch (Exception e) {
1333
+ System . out. println(" Catch Exception -> " + e. getMessage());
1334
+ // 终止当前正在运行的Java虚拟机
1335
+ System . exit(1 );
1336
+ } finally {
1337
+ System . out. println(" Finally" );
1338
+ }
1339
+ ```
1340
+
1341
+ 输出:
1342
+
1343
+ ```
1344
+ Try to do something
1345
+ Catch Exception -> RuntimeException
1346
+ ```
1347
+
1348
+ 另外,在以下 2 种特殊情况下,` finally ` 块的代码也不会被执行:
1349
+
1350
+ 1 . 程序所在的线程死亡。
1351
+ 2 . 关闭 CPU。
1352
+
1353
+ 相关 issue: < https://github.com/Snailclimb/JavaGuide/issues/190 > 。
1354
+
1355
+ 🧗🏻进阶一下:从字节码角度分析` try catch finally ` 这个语法糖背后的实现原理。
1298
1356
1299
- ### 使用 ` try-with-resources ` 来代替 ` try-catch-finally `
1357
+ ### 如何使用 ` try-with-resources ` 代替 ` try-catch-finally ` ?
1300
1358
1301
1359
1 . ** 适用范围(资源的定义):** 任何实现 ` java.lang.AutoCloseable ` 或者 ` java.io.Closeable ` 的对象
1302
1360
2 . ** 关闭资源和 finally 块的执行顺序:** 在 ` try-with-resources ` 语句中,任何 catch 或 finally 块在声明的资源关闭后运行
0 commit comments