1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-25 02:27:10 +08:00

异常部分重构完善

This commit is contained in:
guide 2020-12-05 13:08:51 +08:00
parent 9ed88632a6
commit 1560457c9d

View File

@ -1,5 +1,4 @@
<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} --> <!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} -->
<!-- code_chunk_output --> <!-- code_chunk_output -->
@ -19,16 +18,16 @@
- [1.2.1. 字符型常量和字符串常量的区别?](#121-字符型常量和字符串常量的区别) - [1.2.1. 字符型常量和字符串常量的区别?](#121-字符型常量和字符串常量的区别)
- [1.2.2. 关于注释?](#122-关于注释) - [1.2.2. 关于注释?](#122-关于注释)
- [1.2.3. 标识符和关键字的区别是什么?](#123-标识符和关键字的区别是什么) - [1.2.3. 标识符和关键字的区别是什么?](#123-标识符和关键字的区别是什么)
- [1.2.4. Java中有哪些常见的关键字?](#124-java中有哪些常见的关键字) - [1.2.4. Java 中有哪些常见的关键字?](#124-java-中有哪些常见的关键字)
- [1.2.5. 自增自减运算符](#125-自增自减运算符) - [1.2.5. 自增自减运算符](#125-自增自减运算符)
- [1.2.6. continue、break、和return的区别是什么](#126-continue-break-和return的区别是什么) - [1.2.6. continue、break、和 return 的区别是什么?](#126-continue-break-和-return-的区别是什么)
- [1.2.7. Java泛型了解么?什么是类型擦除?介绍一下常用的通配符?](#127-java泛型了解么什么是类型擦除介绍一下常用的通配符) - [1.2.7. Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符?](#127-java-泛型了解么什么是类型擦除介绍一下常用的通配符)
- [1.2.8. ==和equals的区别](#128-和equals的区别) - [1.2.8. ==和 equals 的区别](#128-和-equals-的区别)
- [1.2.9. hashCode()与 equals()](#129-hashcode与-equals) - [1.2.9. hashCode()与 equals()](#129-hashcode与-equals)
- [1.3. 基本数据类型](#13-基本数据类型) - [1.3. 基本数据类型](#13-基本数据类型)
- [1.3.1. Java中的几种基本数据类型是什么?对应的包装类型是什么?各自占用多少字节呢?](#131-java中的几种基本数据类型是什么对应的包装类型是什么各自占用多少字节呢) - [1.3.1. Java 中的几种基本数据类型是什么?对应的包装类型是什么?各自占用多少字节呢?](#131-java-中的几种基本数据类型是什么对应的包装类型是什么各自占用多少字节呢)
- [1.3.2. 自动装箱与拆箱](#132-自动装箱与拆箱) - [1.3.2. 自动装箱与拆箱](#132-自动装箱与拆箱)
- [1.3.3. 8种基本类型的包装类和常量池](#133-8种基本类型的包装类和常量池) - [1.3.3. 8 种基本类型的包装类和常量池](#133-8-种基本类型的包装类和常量池)
- [1.4. 方法(函数)](#14-方法函数) - [1.4. 方法(函数)](#14-方法函数)
- [1.4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么?](#141-什么是方法的返回值返回值在类的方法里的作用是什么) - [1.4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么?](#141-什么是方法的返回值返回值在类的方法里的作用是什么)
- [1.4.2. 为什么 Java 中只有值传递?](#142-为什么-java-中只有值传递) - [1.4.2. 为什么 Java 中只有值传递?](#142-为什么-java-中只有值传递)
@ -85,7 +84,6 @@
<!-- /code_chunk_output --> <!-- /code_chunk_output -->
## 1. Java 基本功 ## 1. Java 基本功
### 1.1. Java 入门(基础概念与常识) ### 1.1. Java 入门(基础概念与常识)
@ -186,6 +184,7 @@ Java 语言既具有编译型语言的特征,也具有解释型语言的特征
1. 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符 1. 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的 0 个或若干个字符
2. 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置) 2. 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
3. 占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节 (**注意: char 在 Java 中占两个字节**), 3. 占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节 (**注意: char 在 Java 中占两个字节**),
> 字符封装类 `Character` 有一个成员常量 `Character.SIZE` 值为 16,单位是`bits`,该值除以 8(`1byte=8bits`)后就可以得到 2 个字节 > 字符封装类 `Character` 有一个成员常量 `Character.SIZE` 值为 16,单位是`bits`,该值除以 8(`1byte=8bits`)后就可以得到 2 个字节
> java 编程思想第四版2.2.2 节 > java 编程思想第四版2.2.2 节
@ -477,9 +476,6 @@ public native int hashCode();
我们刚刚也提到了 `HashSet`,如果 `HashSet` 在对比的时候,同样的 hashcode 有多个对象,它会使用 `equals()` 来判断是否真的相同。也就是说 `hashcode` 只是用来缩小查找成本。 我们刚刚也提到了 `HashSet`,如果 `HashSet` 在对比的时候,同样的 hashcode 有多个对象,它会使用 `equals()` 来判断是否真的相同。也就是说 `hashcode` 只是用来缩小查找成本。
更多关于 `hashcode()``equals()` 的内容可以查看:[Java hashCode() 和 equals()的若干问题解答](https://www.cnblogs.com/skywang12345/p/3324958.html) 更多关于 `hashcode()``equals()` 的内容可以查看:[Java hashCode() 和 equals()的若干问题解答](https://www.cnblogs.com/skywang12345/p/3324958.html)
### 1.3. 基本数据类型 ### 1.3. 基本数据类型
@ -541,7 +537,7 @@ private static class CharacterCache {
} }
``` ```
两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。** 两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。\*\*
```java ```java
Integer i1 = 33; Integer i1 = 33;
@ -570,6 +566,7 @@ private static class CharacterCache {
``` ```
**应用场景:** **应用场景:**
1. Integer i1=40Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。 1. Integer i1=40Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
2. Integer i1 = new Integer(40);这种情况下会创建新的对象。 2. Integer i1 = new Integer(40);这种情况下会创建新的对象。
@ -578,6 +575,7 @@ private static class CharacterCache {
Integer i2 = new Integer(40); Integer i2 = new Integer(40);
System.out.println(i1 == i2);//输出 false System.out.println(i1 == i2);//输出 false
``` ```
**Integer 比较更丰富的一个例子:** **Integer 比较更丰富的一个例子:**
```java ```java
@ -787,7 +785,7 @@ Java 程序设计语言对对象采用的不是引用调用,实际上,对象
暖心的 Guide 哥最后再来个图表总结一下! 暖心的 Guide 哥最后再来个图表总结一下!
| 区别点 | 重载方法 | 重写方法 | | 区别点 | 重载方法 | 重写方法 |
| :--------- | :------- | :----------------------------------------------------------- | | :--------- | :------- | :--------------------------------------------------------------- |
| 发生范围 | 同一个类 | 子类 | | 发生范围 | 同一个类 | 子类 |
| 参数列表 | 必须修改 | 一定不能修改 | | 参数列表 | 必须修改 | 一定不能修改 |
| 返回类型 | 可修改 | 子类方法返回值类型应比父类方法返回值类型更小或相等 | | 返回类型 | 可修改 | 子类方法返回值类型应比父类方法返回值类型更小或相等 |
@ -795,7 +793,6 @@ Java 程序设计语言对对象采用的不是引用调用,实际上,对象
| 访问修饰符 | 可修改 | 一定不能做更严格的限制(可以降低限制) | | 访问修饰符 | 可修改 | 一定不能做更严格的限制(可以降低限制) |
| 发生阶段 | 编译期 | 运行期 | | 发生阶段 | 编译期 | 运行期 |
**方法的重写要遵循“两同两小一大”**(以下内容摘录自《疯狂 Java 讲义》,[issue#892](https://github.com/Snailclimb/JavaGuide/issues/892) **方法的重写要遵循“两同两小一大”**(以下内容摘录自《疯狂 Java 讲义》,[issue#892](https://github.com/Snailclimb/JavaGuide/issues/892)
- “两同”即方法名相同、形参列表相同; - “两同”即方法名相同、形参列表相同;
@ -1091,7 +1088,6 @@ public class test1 {
- String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。 - String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。
- 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。 - 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
#### 2.5.4. hashCode 与 equals (重要) #### 2.5.4. hashCode 与 equals (重要)
面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?” 面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?”
@ -1176,23 +1172,32 @@ JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道
![](images/Java异常类层次结构图.png) ![](images/Java异常类层次结构图.png)
<p style="font-size:13px;text-align:right">图片来自https://simplesnippets.tech/exception-handling-in-java-part-1/</p> <p style="font-size:13px;text-align:right">图片来自https://simplesnippets.tech/exception-handling-in-java-part-1/</p>
![](images/Java异常类层次结构图2.png) ![](images/Java异常类层次结构图2.png)
<p style="font-size:13px;text-align:right">图片来自https://chercher.tech/java-programming/exceptions-java</p> <p style="font-size:13px;text-align:right">图片来自https://chercher.tech/java-programming/exceptions-java</p>
在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 **Throwable 类**。Throwable 有两个重要的子类:**Exception异常** 和 **Error错误** ,二者都是 Java 异常处理的重要子类,各自都包含大量子类 在 Java 中,所有的异常都有一个共同的祖先 `java.lang` 包中的 `Throwable` 类。`Throwable` 类有两个重要的子类 `Exception`(异常)和 `Error`(错误)。`Exception` 能被程序本身处理(`try-catch`) `Error` 是无法处理的(只能尽量避免)
**Error错误:是程序无法处理的错误**,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVMJava 虚拟机出现的问题。例如Java 虚拟机运行错误Virtual MachineError当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时Java 虚拟机JVM一般会选择线程终止 `Exception``Error` 二者都是 Java 异常处理的重要子类,各自都包含大量子类
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如 Java 虚拟机运行错误Virtual MachineError、类定义错误NoClassDefFoundError等。这些错误是不可查的因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java 中,错误通过 Error 的子类描述。 - **`Exception`** :程序本身可以处理的异常,可以通过 `catch` 来进行捕获。`Exception` 又可以分为 受检查异常(必须处理) 和 不受检查异常(可以不处理)。
- **`Error`** `Error` 属于程序无法处理的错误 ,我们没办法通过 `catch` 来进行捕获 。例如Java 虚拟机运行错误(`Virtual MachineError`)、虚拟机内存不够错误(`OutOfMemoryError`)、类定义错误(`NoClassDefFoundError`)等 。这些异常发生时Java 虚拟机JVM一般会选择线程终止。
**Exception异常:是程序本身可以处理的异常**。</font>Exception 类有一个重要的子类 **RuntimeException**。RuntimeException 异常由 Java 虚拟机抛出。**NullPointerException**(要访问的变量没有引用任何对象时,抛出该异常)、**ArithmeticException**(算术运算异常,一个整数除以 0 时,抛出该异常)和 **ArrayIndexOutOfBoundsException** (下标越界异常)。 **受检查异常**
**注意:异常和错误的区别:异常能被程序本身处理,错误是无法处理。** Java 代码在编译过程中,如果受检查异常没有被 `catch`/`throw` 处理的话,就没办法通过编译 。比如下面这段 IO 操作的代码。
![check-exception](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2020-12/check-exception.png)
除了`RuntimeException`及其子类以外,其他的`Exception`类及其子类都属于检查异常 。常见的受检查异常有: IO 相关的异常、`ClassNotFoundException``SQLException`...。
**不受检查异常**
Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。
`RuntimeException` 及其子类都统称为非受检查异常,例如:`NullPointExecrption``NumberFormatException`(字符串转换为数字)、`ArrayIndexOutOfBoundsException`(数组越界)、`ClassCastException`(类型转换错误)、`ArithmeticException`(算术错误)等。
#### 3.2.2. Throwable 类常用方法 #### 3.2.2. Throwable 类常用方法
@ -1203,14 +1208,14 @@ JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道
#### 3.2.3. try-catch-finally #### 3.2.3. try-catch-finally
- **try 块:** 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。 - **`try`块:** 用于捕获异常。其后可接零个或多个 `catch` 块,如果没有 `catch` 块,则必须跟一个 `finally` 块。
- **catch 块:** 用于处理 try 捕获到的异常。 - **`catch`块:** 用于处理 try 捕获到的异常。
- **finally 块:** 无论是否捕获或处理异常finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时finally 语句块将在方法返回之前被执行。 - **`finally` 块:** 无论是否捕获或处理异常,`finally` 块里的语句都会被执行。当在 `try` 块或 `catch` 块中遇到 `return` 语句时,`finally` 语句块将在方法返回之前被执行。
**在以下 4 种特殊情况下finally 块不会被执行:** **在以下 4 种特殊情况下,`finally` 块不会被执行:**
1. 在 finally 语句块第一行发生了异常。 因为在其他行finally 块还是会得到执行 1. 在 `finally` 语句块第一行发生了异常。 因为在其他行,`finally` 块还是会得到执行
2. 在前面的代码中用了 System.exit(int)已退出程序。 exit 是带参函数 若该语句在异常语句之后finally 会执行 2. 在前面的代码中用了 `System.exit(int)`已退出程序。 exit 是带参函数 若该语句在异常语句之后finally 会执行
3. 程序所在的线程死亡。 3. 程序所在的线程死亡。
4. 关闭 CPU。 4. 关闭 CPU。