---
# System prepended metadata

title: Oracle Certified Professional Java SE 11

---

# Oracle Certified Professional Java SE 11
[TOC]


## 第一章Working with Java Data Types
### 1.java变量命名规则
https://www.cnblogs.com/Yuakk/p/14349555.html
对于java变量的规则，开头不能是数字，且不能只是单一符号，且不能是关键词，但是可以包含关键词。关键词区分大写小写，比如
```java=
int new; //  不可以，非法
int NEW; //  可以，合法
```

### 2.String, StringBuilder, StringBuffer的区别
重点在于，String是不可变类(final class)，所以append等方法都会产生新的Object
而StringBuilder, StringBuffer是可变类(mutable class)，所以append等方法不会产生新的object，区别在于，一个线程安全，一个线程不安全。


注意：String和其他两个都没有继承Iterable，所以不可以直接用for-loop的快捷写法

String与StringBuilder, StringBuffer的性能对比与分析
https://cloud.tencent.com/developer/article/1623342

### 3.题目中的陷阱题总结

| Method | StringBuilder | StringBuffer | String |
| :-----| :----: | :----: | :----: |
| reverse | No | Yes | No |
| charAt | Yes | Yes | Yes |
| length | Yes | Yes | Yes |
| insert | Yes | Yes | No |	
| deleteCharAt | Yes | Yes | No |
### 4.java 操作符的优先级
可以放弃，因为需要记忆太多，需要用到时网上立马查就行。
https://www.sojson.com/operation/java.html
https://blog.csdn.net/chenliguan/article/details/51911906

### 5. String subString
subString(start,end): 它是选择一个半开半闭区间/[/start,end/)/


### 6._下划线的运用
![](https://i.imgur.com/GeEuIRn.png)


### 7.逻辑符号
重点了解一些不熟悉的
https://www.jianshu.com/p/8cf5af30f245
例如： if（a | b）

| 或者 & 表示非终止逻辑符，也就是说，哪怕表达式a为true，它也会继续判断b是否正确, &与之相反，a为false时的情况。
|| 或者 && 表示终止逻辑发，也就是说，只要a对了，它就不会去判断b（直接跳过）。

**补充：&，|，这两个符号还可以用于integer的运算**
![](https://i.imgur.com/cbFmdIH.png)


### 8.Comparator中的参数
![](https://i.imgur.com/JxPdyd1.png)

### Java 数据类型转换(Casting)
https://www.cjavapy.com/article/1584/
总结一下就是：小的可以自动转换成大的（提高精度），大的转换成小的要强制转换，注意，强制转化是**基础数据类型**。
![](https://i.imgur.com/tjuLxZl.png)

如果是他们的**包装类**，则用它们自带的方法进行转换。
![](https://i.imgur.com/4rt8VvQ.png)

题目：这里的promote理解为提升，升级为
![](https://i.imgur.com/TperDUt.png)



### Java 位移操作符 <<,>>
https://blog.51cto.com/u_15185289/2783578
![](https://i.imgur.com/j5y0JKj.png)

需要注意的是，int是32位的，long是64位的，byte,short,char在进行位移操作的时候会先转换成int再进行位移操作。

题目：
![](https://i.imgur.com/qlJmxIL.png)
答案：d



### java基础数据类型的范围
* 8位：byte
* 16位：short
* 32位：int，float
* 64位：long，double
* 其他
![](https://i.imgur.com/SgnXVwi.png)

### java float和double的取值范围和有效范围
https://blog.csdn.net/liyang_nash/article/details/104527239
区分取值范围和有效范围，一个字节的取值范围是-2^7到2^7，float有8bits，double有16bits，
![](https://i.imgur.com/HbnGDBh.png)

![](https://i.imgur.com/pcAStpX.png)

![](https://i.imgur.com/toJPT74.png)


### 数值类数据的除法-除以0
如果是整型数据除以0，就会报错（arithmetic exception），因为整型数据里没有对应的Constant去处理这样的情况，而浮点型数据有这样的常数去处理这种问题：
10/0.0 -> infinity 
0/0.0 -> NaN 
![](https://i.imgur.com/Agr3x4t.png)


### java参数传递的方式
参考：https://www.jianshu.com/p/dbe52fc3f730

![](https://i.imgur.com/j7Uwfzy.png)

解释：
* 当方法的参数为基本数据类型（数字和布尔值）时，该方法不能修改它 。
* 当方法的参数为引用数据类型时，方法会修改参数指向对象的值。


### 包装类(Wrapper Class)，深入理解
原文： https://www.liaoxuefeng.com/wiki/1252599548343744/1260473794166400

总结：
1. 每个基础数据类型都有自己的包装类，且可以Auto Boxing和Auto Unboxing。例如Integer和int：
```java=
// 完整写法
int i = 100;
Integer n = Integer.valueOf(i);
int x = n.intValue();

// 语法糖
Integer n = 100; // 编译器自动使用Integer.valueOf(int)
int x = n; // 编译器自动使用Integer.intValue()
```

2. 所有的包装类型都是不变类。我们查看Integer的源码可知，它的核心代码如下：
```java=
public final class Integer {
    private final int value;
}
```
3. 所有的整数和浮点数的包装类型都继承自Number，因此，可以非常方便地直接通过包装类型获取各种基本类型：
```java=
// 向上转型为Number:
Number num = new Integer(999);
// 获取byte, int, long, float, double:
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();
```
### 强制类型转换-详解
参考： https://blog.csdn.net/CZengze/article/details/52976820
在Java中由于继承和向上转型，子类可以非常自然地转换成父类，但是父类转换成子类则需要强制转换。因为子类拥有比父类更多的属性、更强的功能，所以父类转换为子类需要强制。
![](https://i.imgur.com/3rxW1iu.png)
在第一个例子中，father被指向一个子类对象，子类也可以指向子类对象。而第二个例子中，father被传给一个父类对象，子类引用不能指向父类对象。即很重要的概念是：父类引用指向子类对象。将父类转换为子类之前，应该用**instanceof**检查。
![](https://i.imgur.com/yREWEQW.png)
向上转型是安全的，但是会有些子类特性会丢失，向下转型可以成功。

总结：父类引用可以指向子类对象，子类引用不能指向父类对象。把子类对象直接赋给父类引用叫做向上转型，向上转型不用强制转型，如Father f1=new Son()，把指向子类对象的父类引用赋给子类引用叫做向下转型，要强制转型，如Son s1 = (Son)f1。向上转型会丢失子类特有的方法，但是子类overriding父类的方法，子类方法有效。



### 错题库
29，30


##  第二章Controlling Program Flow
### 1.合法在switch中使用的type
Swtich的规则
1.1 只有基础类型，String，和他们的封装类，var（之前定义为上面说的那些类型）才可以在Switch中使用，但是浮点型数据**float，double以及他们的封装类不可以在switch中使用**。
https://www.runoob.com/java/java-switch-case.html
![](https://i.imgur.com/QGIXJnT.png)

1.2 通用规则
重点：Switch可以有多个case，用simcolon“：”隔开。Default可有可无，位置任意，break也是可有可无。
![](https://i.imgur.com/L6Gqu4L.png)






### 2.使用for-each loop
要使用for each loop需要该Class implement java.lang.Iterable,而String，StringBuilder,StringBuffer都**没有实现**Iterable，List,Array**实现了**Iterable
![](https://i.imgur.com/OusGH2x.png)


### 3. 循环别名
就是在一个循环开始的时候起个名字，比如下面这题中的loop，你可以起其他的名字，这有点“函数式编程”的味道。当你需要对这个循环体进行操作的时候，就可以简单的使用这个别名loop。
提醒：**这个别名不能用在循环体之外**
![](https://i.imgur.com/8C8NUg4.png)


### 4. 对final关键字的浅浅理解
final关键词如果修饰的variable变量的话，那么它是指这个变量不可以发生改变，但是如果final修饰的是Object的话，它是指这个Obejct的**地址**不可以发生改变，如果是修饰方法，那就表示该方法不能被override。
![](https://i.imgur.com/kJn58z4.png)


### 5. 去掉花括号{}
去掉花括号而不影响结果：
* 如果if或者else后面只跟一句话，那么就可以不用写花括号
* 如果for，while后面也只有一个循环体/if else，也就是一个完整的语句，那就不用写
![](https://i.imgur.com/QqsPOga.png)

### 题目8
![](https://i.imgur.com/tISQFya.png)
注意这里
```java=
plan = plan++ + --plan;
//先执行plan++（1） + --plan（0）
//使得plan等于1,但是plan++优先级比较低但是也比=高，
//所以最好要执行plan++, = 2
```
![](https://i.imgur.com/j9FdtAh.png)
### 题目15
![](https://i.imgur.com/cRxrZhI.png)
### 题目30(TNND，给老子玩阴的)
![](https://i.imgur.com/oEteggW.png)



### 错题库
8，12，15，16，17，25，27，28，30


##  第三章Java Object‐Oriented Approach
### 访问修饰符
![](https://i.imgur.com/AliQYUd.png)

### 对extend，implement的要求
* abstract class中的变量或者方法不能是private，final，因为这些关键字限制了使用范围，意味着不能被subclass使用，那么继承就毫无意义

### 静态变量和实例变量
#### 定义：
**静态变量**：
static修饰的成员变量叫做静态变量【也叫做类变量】，静态变量是属于这个类，而不是属于是对象。
**实例变量**：
没有被static修饰的成员变量叫做实例变量，实例变量是属于这个类的实例对象。
还有一点需要注意的是：static是不允许用来修饰局部变量，不要问我问什么，因为java规定的！


#### 区别：
**静态变量**：
静态变量由于不属于任何实例对象，属于类的，所以在内存中只会有一份，在类的加载过程中，JVM只为静态变量分配一次内存空间。
**实例变量**：
每次创建对象，都会为每个对象分配成员变量内存空间，实例变量是属于实例对象的，在内存中，创建几次对象，就有几份成员变量。


### Static的理解
出处：https://juejin.cn/post/6844903988098236429
总结起来就是：
1. static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象，也能使用属性和调用方法！
**1.2.** static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方，类中可以有多个static块。在类初次被加载的时候，会按照static块的顺序来执行每个static块，并且只会执行一次。
**1.3.** 为什么说static块可以用来优化程序性能，是因为它的特性:只会在类加载的时候执行一次。因此，很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
2. 被static修饰的变量或者方法是独立于该类的任何对象，也就是说，这些变量和方法不属于任何一个实例对象，而是被类的实例对象所共享。
3. 访问限制
**3.1. 静态只能访问静态。 
3.2. 非静态既可以访问非静态的，也可以访问静态的。**


### final关键词
出处：https://blog.csdn.net/qq_44543508/article/details/102720206

### 总结
1. 修饰类：final修饰一个类时，表明这个类不能被继承。
2. 修饰方法：final修饰方法，方法不可以重写，但是可以被子类访问 【前提：方法不是 private 类型】。
3. 修饰变量：如果被final修饰的是基本数据类型的变量，则其数值一旦在初始化之后便不能更改；如果是引用类型的变量，则在对其初始化之后便不能再让其指向另一个对象。
4. final变量修饰变量（成员变量、局部变量）：
**final修饰成员变量**：a. 成员变量必须在定义时或者构造器中进行初始化赋值; b.final变量一旦被初始化赋值之后，就不能再被赋值了。【注意是成员变量】
**inal修饰局部变量**: a. 只需要保证在使用之前被初始化赋值即可
5. final变量和普通变量的区别:![](https://i.imgur.com/dDbw6Kh.png)
6. 被final修饰的引用变量一旦初始化赋值之后指向的对象不可变但该对象的内容可变
7. final是在**编译时**才会确定变量或者对象的具体值是什么![](https://i.imgur.com/5HpHlFu.png)

**！！！以上内容都出自上面的文章链接里，建议阅读全文，因为写得真的很好。**


### 多态（Polymorphism）
出处：https://segmentfault.com/a/1190000022705651
#### 总结：
* 父类类名 引用名称 = new 子类类名();
当是多态时，该引用名称只能访问父类中的属性和方法，但是访问的时候，**会优先访问子类重写以后的方法**。
* 多态中的类型转换
**1.向上转型**
向上转型，也叫做自动类型转换，子类型赋值给父类型（父类型的引用指向子类型），构成多态
父类类型 引用名称 = new 子类类名();
当使用多态方式调用方法时，该引用名称只能访问父类中的属性和方法。编译器首先检查父类中是否有该方法，如果没有，则编译错误。如果有，再去调用子类的同名（重写）方法。
**2.向下转型**
向下转型，也叫做强制类型转换，父类型赋值给子类型
当使用多态时，并且访问子类独有的属性或方法时，则必须进行向下转型
当进行向下转型时，建议先使用 instance of 关键字进行判断，判断合法时，则在转为对应的类型，否则可能会出现类型转换异常 java.lang.ClassCastException。
说明：instance of 关键字用于判断一个对象，是否属于某个指定的类或其子类的实例

### 重写（Override）
注意点：子类重写的方法的访问等级不能低于父类中的被重写方法
![](https://i.imgur.com/h9fKbQa.png)

### 抽象类和接口的一些使用限制
1. Abstract interface methods are always public
2. 方法不能即使final又是abstract

### Static在interface中
interface中的方法不可以用final，但是可以用public或者private修饰static的变量。
![](https://i.imgur.com/OHjh7XW.png)


### Functional interface初步了解
简单来说
只包含一个**abstract**方法的interface是functinal interface，并且可以用lamda表达式。
![](https://i.imgur.com/0AxoAzl.png)

### Enum枚举类
* 小结：
1.定义的enum类型总是继承自java.lang.Enum，且无法被继承；
2.只能定义出enum的实例，而无法通过new操作符创建enum的实例；
3.定义的每个实例都是引用类型的唯一实例；
4.可以将enum类型用于switch语句。
https://www.liaoxuefeng.com/wiki/1252599548343744/1260473188087424


* 这篇更加基础好懂
https://www.cnblogs.com/ziph/p/13068923.html
* 题目
1.枚举类不能出现再非静态的内部类里！！
2.枚举类在switch中使用时，不用带class名（case或者判断条件中）
![](https://i.imgur.com/CNgaLdp.png)
![](https://i.imgur.com/zKDCV9v.png)


### hiding AND overriding 隐藏与覆盖
https://blog.csdn.net/weixin_28703451/article/details/114623179
* 小结：
**类变量**：又叫静态变量，这种变量属于类，通过类名就可以访问类变量。
**实例变量**：属于类的实例即对象，通过对象可以访问实例变量，但是不能通过类名访问实例变量。
**静态方法**：方法属于类，通过对象访问实例方法，不能通过类名访问实例方法。
**隐藏**：B隐藏了A的变量或者方法，那么，B不能访问A被隐藏的变量或方法，但是，将B转换成A后，可以访问A被隐藏的变量或方法。
**覆盖**：B覆盖了A的变量或者方法，那么，B不能够访问A被覆盖的变量或方法，将B转换成A后，同样不能访问A被覆盖的变量或方法。
**Java中方法和变量在继承时的覆盖与隐藏规则如下**：
 1.父类的实例变量和类变量能被子类的同名变量隐藏。
2.父类的静态方法被子类的同名静态方法隐藏。
3.父类的实例方法被子类的同名实例方法覆盖。
4.不能用子类的静态方法隐藏父类中同样标识的实例方法，否则编译器将会报错。
5.不能用子类的实例方法覆盖父类中同样标识的静态方法，否则编译器会报错。
6.最终方法(带关键字final的方法)不能被覆盖。
7.变量只会被隐藏，不会被覆盖，无论她是实例变量还是静态变量。而且，子类的静态变量可以隐藏父类的实例变量，子类的实例变量可以隐藏父类的静态变量。

![](https://i.imgur.com/vuInSVl.png)


### java 的接口可以实现接口吗?抽象类呢?
出处：https://blog.csdn.net/jianjun4833/article/details/72155890
![](https://i.imgur.com/B9oXWVv.png)
![](https://i.imgur.com/hhyC516.png)
![](https://i.imgur.com/XUubZKi.png)

### defualt关键词在interface中的作用
原文： https://blog.csdn.net/qq_37909508/article/details/106483918
![](https://i.imgur.com/FBs6xxy.png)
![](https://i.imgur.com/Kj5qkK9.png)

### Java的静态方法不能被重写（详解！）
https://blog.csdn.net/gao_zhennan/article/details/72892946

### 错题库
1（对于题目的理解），10（死记），11（多态），12（default的使用范围），14，15，16（值得考前再看看，如果正确的情况），24(涉及到函数式接口，重点多看)，27，29,30,31，33（枚举运用，没理解），34，35，38,40,41(死记，必要)，42，43,45(public static interface),46,47,50,54(优先复习，default关键词不能出现在实例方法中)，58


##  第四章Exception Handling
### Exception的继承图

![](https://i.imgur.com/iYACT7f.png)

#### Java里面异常分为两大类
Java里面异常分为两大类:checkedexception(检查异常)和unchecked exception(未检查异常)，对于未检查异常也叫RuntimeException(运行时异常),对于运行时异常，java编译器不要求你一定要把它捕获或者一定要继续抛出，但是对checkedexception(检查异常)要求你必须要在方法里面或者捕获或者继续抛出。
链接：https://juejin.cn/post/6859749627827060750

题目：![](https://i.imgur.com/D21orFF.png)

#### 补充：
**unchecked exception**:
UnsupportedOperationException 
IllegalStateException 
IllegalArgumentException 
ClassCastException 
**checked exception**:



#### Error
注意一点就好了：The program runs out of memory和stack overflow这种情况归Error管，不归Exception
题目：
![](https://i.imgur.com/4Qgv5gE.png)



#### Exception的构造器，需要稍微记住排在前面的几个
![](https://i.imgur.com/ahOkdNb.png)
题目：![](https://i.imgur.com/rOeYoOn.png)


### try catch运行图
![](https://i.imgur.com/hALewqn.png)
### try‐with‐resources statement
理解：https://developer.aliyun.com/article/269349
#### 简单概括：
1.try-with-resources语句是一个声明一个或多个资源的 try 语句。一个资源作为一个对象，必须在程序结束之后随之关闭。 try-with-resources语句确保在语句的最后每个资源都被关闭。

2.任何实现了 java.lang.AutoCloseable的对象, 包括所有实现了 java.io.Closeable 的对象, 都可以用作一个资源。并且Closeable extends AutoCloseable。
![](https://i.imgur.com/S36KIrb.png)


3.在关闭资源的时候，会按照**从下往上**的顺序关闭
题目:![](https://i.imgur.com/JVcd6q4.png)

4.If the **try** block and **close()** method both throw an exception, then the one thrown by the close() method is **suppressed**.


5.
![](https://i.imgur.com/Y5qPBxd.png)

#### 与try catch的区别
![](https://i.imgur.com/JiRbtps.png)

### throw与throws关键字的用法区别
* throw: 用来抛出异常(对象)
例如: throw new NumberFormatException(); 
* throws：用来定义方法需要抛出的异常（名字）
例如：public static void function() throws NumberFormatException{...}

### catch中存在多个exception的情况
1. 多个exception共享一个变量名
ProblemException | RuntimeException e
2. exception之间不能是对方的子类
题目：
![](https://i.imgur.com/l7JczmW.png)

### 对含有throws的方法进行重写override
* 一点需要注意，可以对含有throws进行override，但是override的方法，它throws出来的excetion的种类的范围不能大于被override的。简单来说，override方法throws出来的exception要么和被override的**一样**，那么是它的**subclass**。
题目：
![](https://i.imgur.com/9Zc4Kc1.png)


* 但是对于throws这个关键词在方法声明中，它抛出的exception的范围可以小于实际抛出的，看下面题目
题目：
![](https://i.imgur.com/2jHtaTF.png)



### 关于嵌套在try-catch中的try-catch相关限制
简单来说，从下面的图可以看出，平行的catch block可以取一样的变量名，但是如果写在一个catch block中的try-catch中的catch就不能用同样的变量名。如果还不理解，做下面的题
![](https://i.imgur.com/XiCoV8S.png)

题目：
![](https://i.imgur.com/e2seNT6.png)

### 对于check exception，如果没有对应的，就不要写在catch中，否则会complier error
题目：
![](https://i.imgur.com/qELF4GO.png)


但是，方法声明中throws没有这种限制。



### 错题库
2,4，6，7，10,11(很傻逼的题)，12，13，15,16,17,18,22（记忆），23（重点），26（记忆），29（考前需要再看一眼），31,36,39(纯属傻逼题)，43,46,47，48（新类型，值得看），50（看），52（值得看），55，57,58

## 第五章Working with Arrays and Collections
### Array和ArrayList的创建规则
#### Array创建规则
https://blog.csdn.net/u014199097/article/details/50551731
总结来说：
1.声明：type[] arrayName; 或 type arrayName[]; 并且声明数组的时候不能指定其大小
2.创建数组，如果在创建的同时不初始化数组则必须指定其大小
 intArray0 = new int [3];
3.创建数组时，不指定数组大小则必须在创建的同时初始化数组
   intArray1 = new int []{0,1,2};
4.静态初始化
 int intArray2 [] = new int []{20,21,22};
  静态初始化简化方式
 int intArray3 [] = {30,31,32};
5.动态初始化
 int [] intArray4 = new int [3];
6.错误写法：静态初始化不能指定元素个数
 int intErrorArray5[] = new int[3]{50,51,52};
 错误写法：动态初始化必须指定元素个数
 int intErrorArray6[] = new int[];
#### ArrayList的四种创建规则
https://blog.csdn.net/u011523796/article/details/79537055
常见的两种
![](https://i.imgur.com/GFpGFHv.png)

### 泛型generics
https://www.runoob.com/java/java-generics.html
https://blog.csdn.net/claram/article/details/51889214
#### 定义以及好处
泛型是Java SE 1.5的新特性，泛型的本质是参数化类型，也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中，分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

用来实现参数的“任意化”，“任意化”带来的缺点是要做显式的强制类型转换，而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况，编译器可能不提示错误，在运行的时候才出现异常，这是一个安全隐患。

泛型的好处是在编译的时候检查类型安全，并且所有的强制转换都是自动和隐式的，以提高代码的重用率。

#### 符号
注意，除了？问号以外，其他的都只是**约定俗成**而不是**强制**的，你可以用**26个大写字母**代替下面的任意一种。
E - Element (在集合中使用，因为集合中存放的是元素)
T - Type（Java 类）
K - Key（键）
V - Value（值）
N - Number（数值类型）
？ - 表示不确定的 java 类型

**另外**：The ? wildcard cannot be used when instantiating a type on the right side of the assignment operator.问号不能在初始化对象的时候放在右边！

题目：
![](https://i.imgur.com/Vm38wpl.png)


#### 规则
泛型好文章： https://blog.csdn.net/s10461/article/details/53941091
1.泛型的类型参数只能是**类类型**（包括自定义类），不能是简单类型；
2.同一种泛型可以对应多个版本（因为参数类型是不确定的），不同版本的泛型类实例是不兼容的；
3.泛型的类型参数可以有多个；
4.泛型的参数类型可以使用extends、super语句，例如。习惯上称为“有界类型“；
5.泛型的参数类型还可以是通配符类型。例如
```=java
Class<?> classType=Class.forName("java.lang.String")
```
![](https://i.imgur.com/UWoRdfh.png)
![](https://i.imgur.com/yi437El.png)
![](https://i.imgur.com/S84sc6z.png)
必须定义泛型，才能使用，这里的定义是指，在Class或者Medthod声明的时候有出现过
![](https://i.imgur.com/3oPwY2e.png)


#### 泛型对象的创建的规则
一般来说，如果diamond operator (<>)里面什么都没有写，那就等同写了Object，并且等号的左边不能有空的diamond operator (<>)。
![](https://i.imgur.com/ihWpx6B.png)

### 队列常见方法
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayDeque.html
记忆几种就行，因为很多类队列数据都有差不多的使用方法。
| 方法 | 描述 |
| :----: | :----: |
| offer(E e) | Inserts the specified element at the end of this deque.（注意是把元素放在列队的最后） |
| offerFirst(E e)  | Inserts the specified element at the front of this deque |
| peek()  | Retrieves, but does not remove, the head of the queue represented by this deque, or returns null if this deque is empty.（注意不删除元素） |
| poll()  | Retrieves and removes the head of the queue represented by this deque (in other words, the first element of this deque), or returns null if this deque is empty.（注意这个要删除元素） |
| pop()  | Pops an element from the stack represented by this deque. |
| push()  | Pushes an element onto the stack represented by this deque. |
| 单元格  | 单元格 |
| 单元格  | 单元格 |

题目：
![](https://i.imgur.com/XNsJTJy.png)

### ArrayList不常见方法
| 方法 | 描述 |
| :----: | :----: |
| 	set(int index, E element)  | Replaces the element at the specified position in this list with the specified element.（注意是replace，估计别的数据结构也没有这个方法） |
| 单元格  | 单元格 |

### Arrays接口不常见方法
| 方法 | 描述 |
| :----: | :----: |
| compare（T a, T b）  | Compares two int arrays lexicographically.按字典顺序比较两个对象，一般是数组 |
| 	mismatch（T a, T b）  | Finds and returns the index of the first mismatch between two T arrays, otherwise return -1 if no mismatch is found. |
| 单元格  | 单元格 |
| 单元格  | 单元格 |

题目：
![](https://i.imgur.com/QY1JfRc.png)


### Set不常见方法
List接口与Set接口类似
| 方法 | 描述 |
| :----: | :----: |
| 	copyOf(Collection)  | Returns an unmodifiable Set containing the elements of the given Collection.（注意是unmodifiable） |
| of()  | Returns an immutable list containing zero elements.注意是unmodifiable） |
| of(E... elements) | Returns an immutable list containing zero elements.注意是unmodifiable） |

### Comparator的使用
注意：compareTo()方法是Object的方法！！！
https://www.cnblogs.com/yangxiaoli/p/13743639.html
https://www.jianshu.com/p/81e5c3e88fc6
#### 简单来说有两种使用方式
![](https://i.imgur.com/jbPwKXq.png)
2.使用匿名类
![](https://i.imgur.com/E66jIBH.png)
#### 判断大小的标准
x.compareTo(y) 来“比较x和y的大小”。若返回“负数”，意味着“x比y小”；返回“零”，意味着“x等于y”；返回“正数”，意味着“x大于y”。
1.实现Comparator<T\>接口

题目：
![](https://i.imgur.com/E4jxPSK.png)


### 记忆一下Map与其他数据结构的区别
![](https://i.imgur.com/DDGnelt.png)

### Arrays.binarySearch() 相关问题
这篇文章十分通透
https://www.cnblogs.com/qingergege/p/5658292.html

总结：binarySearch()方法的返回值为：
1、如果找到关键字，则返回值为关键字在数组中的位置索引，且索引从0开始
2、如果没有找到关键字，返回值为负的插入点值，所谓插入点值就是第一个比关键字大的元素在数组中的位置索引，而且这个位置索引从1开始。

注意：*调用binarySearch()方法前要先调用sort方法对数组进行排序，否则得出的返回值不定，这时二分搜索算法决定的。*

题目：
![](https://i.imgur.com/QdegBp2.png)

题目2：
![](https://i.imgur.com/wwsXWl2.png)


### 数据结构的有序性与所保存的数据是否有序
https://blog.csdn.net/WinstonLau/article/details/100881635
首先，这是两个概念！！
比如我们要加入[1,3,2,2]
1.数据结构的有序性是指集合的有序性，通俗来讲，**加入元素的顺序就是存放的顺序**，比如List，你可以用list.get(index)去获取到你能够期望的结果。list应该为[1,3,2,2]。
无序是指，**加入元素的顺序不等于存放的顺序**，比如Set,如果使用的是TreeSet那么加入的数据会去重并且自动排序。所以结果应该为[1,2,3]
注意：Map也是无序的，但是LinkedHashMap是有序的，LinkedHashSet 是有序的

2.所保存的数据是否有序
这个指的是，加入进去的元素是否会顺序保存，比如上面提到的TreeSet数据结构就是保存有序的，它会自动排序。


#### 记忆
https://zhuanlan.zhihu.com/p/55840526
*  接口的三个实现类：ArrayList、LinkedList、Vector 均按添加时的顺序存放，不自动排序，若是需要自动排序，可以使用 Collections.sort 方法排序，它默认按自然顺序排序，也可以通过添加比较器实现自定义排序；

* Set 接口的三个实现类：HashSet、TreeSet 有序，默认按自然顺序排序，可通过构造器传入自定义的比较器自定义排序策略，但是，LinkedHashSet无序

* HashMap 是有序的，存数据的时候默认按 key 排序，因为它按二叉树结构存储数据

* TreeMap 有序，他是红黑树的实现

* ConcurrentHashMap 有序

* Hashtable 不是有序的，因为他是数组实现的，不是二叉树

* LinkedHashMap 不是有序的，他虽然使用的是 HashMap 的 put 方法，但是他并没有使用二叉树，使用的是 Node 数组
显然 树 的存在就是为了有序，不然如何快速查找


题目：
![](https://i.imgur.com/mENGJZK.png)


### 错题库
1，2，4(多看，需要记忆)，7（看不懂就算了），11，12（必会题），14，15，17（多多注意呀，想要比较，需要class继承Comparable），18,20(值得看),22(可以考前记忆)，26，27（不是很懂，考前可以记忆一下），30（用List.of()生成的list是不可变的,并且ArrayList只能放一个int value，new的时候，或者一个collection），31（不懂），33（看懂它），34，36，37(优先复习)，41（多看），42（值得多看），44（考前必看），48（有点不能理解，有点混乱），50（记忆与19一起），51（记忆与8一起），52，53


## 第六章Working with Streams and Lambda Expressions
### Stream的工作流程
如图F答案所示
没有前面两个步骤Stream照样可以工作，但是没有terminal operation就无法工作。
![](https://i.imgur.com/gWBGZxl.png)


### Steam中常见的方法
| 方法 | 描述 | 
| :---- | :---- | 
| empty()  | Returns an empty sequential Stream. |
| findAny()  | Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty. |
| findFirst()  | Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. |
| max(Comparator<\? super T\> comparator\)  | Returns the maximum element of this stream according to the provided Comparator. |
| peek(Consumer<\? super T\> action\)  | Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. |
| skip(long n)  | Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. |
| 	anyMatch(Predicate<\? super T\> predicate\)  | Returns whether any elements of this stream match the provided predicate. |
| 	collect(Collector<\? super T,A,R> collector\)  | Performs a mutable reduction operation on the elements of this stream using a Collector. 对collect函数的理解：https://juejin.cn/post/6844903497666674702|
| reduce(T identity, BinaryOperator<T\> accumulator\)  | 简单来说就是聚合，第一个参数是聚合的初始值，第二个是怎么聚合。理解可以看下面的地址 https://www.liaoxuefeng.com/wiki/1252599548343744/1322402971648033 |


### 需要记忆的functional interface
https://www.runoob.com/java/java8-functional-interfaces.html
全部出自java.util.function package，这几种就是基础类型，其他的扩展类型都是在这些的基础上展开的，所以只要记住这几种，其他的看接口名字就能够知道作用是什么。
| 接口 | 描述 | 方法 | 方法描述 |
| :---- | :---- | :----: | :----: |
| Supplier<T\>  | 无参数，返回一个结果。 |T get()|Gets a result. |
| Predicate<T\>  | 接受一个输入参数，返回一个布尔值结果。（注意返回的是初始类型的boolean，不是它的包装类Boolean） |boolean test(T t)|true if the input argument matches the predicate, otherwise false |
| Consumer<T\>  | 代表了接受一个输入参数并且无返回的操作 |void accept(T t) |Performs this operation on the given argument.|
| Function<T,R\>  | 接受一个输入参数，返回一个结果。 |R apply(T t) |Applies this function to the given argument. AND return the function result|
| UnaryOperator<T\>  | 接受一个参数为类型T,返回值类型也为T。 |static <T\> UnaryOperator<T\> identity() |Returns a unary operator that always returns its input argument.|
| 单元格  | 单元格 |单元格 |单元格|
| 单元格  | 单元格 |单元格 |单元格|
| 单元格  | 单元格 |单元格 |单元格|

题目：
![](https://i.imgur.com/8bIyXkV.png)

### JAVA 中的Optional类理解、学习与使用
https://blog.csdn.net/qq_37840993/article/details/116120837
这篇文章已经讲的非常好了，具体可以深入阅读
#### 总结：
Optional类是Java8新引进的一个主要用于解决的问题是臭名昭著的空指针异常（NullPointerException|）的一个类。
本质上，这是一个包含有可选值的包装类，这意味着 Optional 类既可以含有对象也可以为空。
![](https://i.imgur.com/grdfydC.png)

#### Optional常见的方法
| 方法 | 描述 | 
| :---- | :---- | 
| empty()  | Returns an empty Optional instance. |
| isPresent()  | Return true if there is a value present, otherwise false. |
| 	ifPresent(Consumer<\? super T\> consumer\)  | If a value is present, invoke the specified consumer with the value, otherwise do nothing |
| of(T value)  | Returns an Optional with the specified present non-null value. |
| ofNullable(T value)  | Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional. |
| orElse(T other)  | Return the value if present, otherwise return other. |
| get()  | If a value is present in this Optional, returns the value, otherwise throws NoSuchElementException.(注意null的时候会报错) |
| 单元格  | 单元格 |

题目：
![](https://i.imgur.com/uslbcdh.png)

### Reduction的概念
![](https://i.imgur.com/NiCQiEr.png)

按照我的理解
* reduction 就是计算公式，你想对提供的数据做什么操作
* Collector argument就是聚合器，把各方的结果集合起来
* 下图可以方便理解https://juejin.cn/post/6844903497666674702

![](https://i.imgur.com/OYayGm3.png)

题目：
![](https://i.imgur.com/4dDqD6V.png)



### flatMap和map的区别
https://www.cnblogs.com/yucy/p/10260014.html

题目：
![](https://i.imgur.com/xJlTwfS.png)

### ArrayList::new 带有两点的写法，正式称呼method reference
这个是调用了Function<Integer, ArrayList>，翻译过来就是-> new ArrayList<>();或n-> new ArrayList<>(n);
题目：
![](https://i.imgur.com/5DMJ1Yq.png)



### 错题库
4（多看），5，6（重点），7，10（记忆与23一起），12，13（值得多看），15（不是很懂，但是记住这种题要求接受一个泛型返回int就行），16（多看多看，很重要），17（经典），19，21（重点题flatMap与Map），22（惊了，long可以cast to double）,23(记忆与10一起)，24，25（出这种题没什么水平，纯背），27,29（确实），30，31（forEach只能使用一次，不然会报错），32，34（多看，如果这些函数式接口没有写明，就是object类型，那么就需要考虑object是否存在提供的方法），35，36（好题目,有时间可以看），41（非常多不懂！！！），43，44，45，46（可），47(generator生成的无限Stream)，48,50,62,82,88,99,111,117








## 第七章Java Platform Module System
### Module模块
https://www.liaoxuefeng.com/wiki/1252599548343744/1281795926523938
简单来说，我们为什么要用模块，因为在模块出现之前，我们都是需要依赖各个class文件（或者jar包）来实现整个project的运行，一旦出现其中某个或者某些class没有依赖上，就会报错，很麻烦。但是有了模块之后，我们只需要在专门的module-info.java文件中写入我们依赖的就可以了。可以理解为Maven（我感觉maven更好）。

阅读： https://www.cnblogs.com/flydean/p/jdk9-java-module-jpms.html

### Module中的几个关键字
https://zhuanlan.zhihu.com/p/134676479
You need to know these keywords: exports, requires, requires transitive, provides, opens, and uses.
#### requires
表示这个模块依赖哪些模块，其实java.base不需要明确requires，是默认的。
```java=
requires java.base;
requires java.compiler;
```

#### exports
表示这个模块向外暴露哪些包，这个是在编译时可以引用的包。注意，JDK9之后的版本，因为引进了Module，所以限制了public的作用范围，如果你要requires一个模块，那么这个模块需要事先exports。
```java=
// 第一种用法
exports icu.mianshi.openjdk.compiler;

// 第二中用法见下图
// com.duck to allow the com.park module to reference
//  the Duckling class but not allow the com.bread module
exports com.duckling to com.park;
```
![](https://i.imgur.com/51O0rRB.png)


#### opens
这个也表示这个模块的暴露哪些包，只不过是运行时可用，就是编译时不能引用，但是可以用反射的方法调用。
```java=
opens icu.mainshi.oepnjdk.ref;
```


#### provides
表示这个模块提供的接口或是虚类的实现，可以通过java.util.ServiceLoader来加载实现的。
```java=
provides icu.mianshi.openjdk.service.ICompilerService
			with icu.mianshi.openjdk.serviceimpl.JavaCompilerService;
```


#### uses
表示这个模块要用到的另人申明的接口或是虚类。
```java=
uses javax.annotation.processing.Processor;
```

#### Module运行步骤
1. 加载requires里早申明的module里exports的所有包，这就是这个Module所能用到的包。
2. 把这个包以及它所exports里的类放到Symtab里的。（Symtab是事个编译器所有类型所在的一个HashMap)
3. 检查是不是有循环引用的module.

如果没找到module-info.java，那么这个module就一个unnamed的module,它所有的类可见与Java8之前的一样。

### Module的命名规则
Module names are permitted to be any valid variable name with the addition of dot separators (.)
![](https://i.imgur.com/C3UAGwo.png)



### 理解ServiceLoader
https://zhuanlan.zhihu.com/p/212850943
ServiceLoader是Java提供的一套SPI（Service Provider Interface，常译：服务发现）框架，用于实现服务提供方与服务使用方解耦


辅助理解： https://openhome.cc/Gossip/Java/ServiceLoader..html

目前最好的文章： https://www.cnblogs.com/IcanFixIt/p/7050433.html
![](https://i.imgur.com/JOfBtyj.png)

#### 使用ServiceLoader.load()
![](https://i.imgur.com/9TQdDVV.png)


#### 使用ServiceLoader好处
![](https://i.imgur.com/krmYtlI.png)
![](https://i.imgur.com/9dufoGV.png)


### named module，automatic module，unnamed modules
* **named module**：A named module must be on the module path and contain a module‐info file.
* **automatic module**：An automatic module must be on the module path but does not contain a module‐info file.
* **unnamed modules**：An unnamed module must be on the classpath. It is rare to have a module‐info file in an unnamed module, but it is allowed. 

题目：区分哪些是named module，automatic module，unnamed modules
![](https://i.imgur.com/7yU5MiI.png)

答案：named module=1，automatic module=1，unnamed modules=2


#### 用module的好处
![](https://i.imgur.com/ME1ZLpS.png)
![](https://i.imgur.com/CNZTkZm.png)



### Module相关command总结
| 方法 | 描述 | 
| :---- | :---- | 
| ‐‐add‐exports | 添加exports包到module | 
|‐‐list‐modules|list all the modules that come with the JDK|
|‐‐describe‐module|可以看某模块的具体信息|
|‐‐show‐module‐resolution|Shows module resolution output during startup|
|–d |specifies the directory|
|–p|specifies the module path|
|jdeps |The jdeps command lists information about dependencies within a module.|
|–s |provides a summary of output（在jdeps中出现的-s的作用）|
|||

* ‐‐list‐modules
![](https://i.imgur.com/O3uv3Tf.png)

* ‐‐describe‐module
![](https://i.imgur.com/3otkwmL.png)

* ‐‐show‐module‐resolution
出处：https://stackoverflow.com/questions/48339598/list-the-modules-resolved-during-the-application-startup
![](https://i.imgur.com/W5pORbR.png)
```java=
Jigsaw git:(master) ✗ ../jdk-9.0.1.jdk/Contents/Home/bin/java 
                       --show-module-resolution 
                       -p ../out/production/100DaysOfJava9 
                       -m HundredDaysOfJavaNine/com.stackoverflow.nullpointer.Challenge1
```

### service provider interface and service provider,consumer and service locator的区别（概念上）
* **service provider interface**：All parts of a modules service must point to the service provider interface.
* **service provider**：nothing has a direct dependency on the service provider.
* **consumer**：The consumer depends on the service provider interface and service locator, but not the service provider.
* **service locator**：The service locator references the service provider interface directly and the service provider indirectly.
* **service part**: Only the service locator and service provider interface are part of the service

题目：
虚线表示间接依赖，实线表示直接依赖
![](https://i.imgur.com/qUMtC8L.png)
![](https://i.imgur.com/YAPExbt.png)
![](https://i.imgur.com/TtbeeVU.png)

**Shared modules** are the smallest unit of resources that are named, versioned, and packaged as part of an application and can be used by other modules that are part of the same application.
![](https://i.imgur.com/d5DNCOw.png)


#### 概念题目，集中记忆Service locator
![](https://i.imgur.com/NA44AQ4.png)
![](https://i.imgur.com/7SNTFLM.png)
![](https://i.imgur.com/X7alsou.png)
![](https://i.imgur.com/SG0yiRx.png)
![](https://i.imgur.com/c1bRDvG.png)
![](https://i.imgur.com/gFJaQgt.png)

![](https://i.imgur.com/VQXQJYV.png)
![](https://i.imgur.com/bTCv1Qh.png)
![](https://i.imgur.com/5yqwabt.png)
![](https://i.imgur.com/krAu3KH.png)
![](https://i.imgur.com/Cfumkl3.png)








### 概念题目，集中记忆2
![](https://i.imgur.com/qYD3M4u.png)
![](https://i.imgur.com/xuEAUBi.png)
![](https://i.imgur.com/qYTCyvv.png)


### 概念题目，集中记忆3
![](https://i.imgur.com/kbRkaIc.png)
Suppose we want to have two modules: com.ny and com.sf. Which is true about the placement of the module‐info.java file(s)?
![](https://i.imgur.com/74RW5ZQ.png)
![](https://i.imgur.com/mKbfIVb.png)
![](https://i.imgur.com/YvRJ1Rf.png)
![](https://i.imgur.com/t0mqpJD.png)
![](https://i.imgur.com/VX11h9G.png)
![](https://i.imgur.com/YMeKdae.png)
![](https://i.imgur.com/1vm5YON.png)


### 概念题目，集中记忆4
![](https://i.imgur.com/kh6dfkv.png)
Suppose we have the packages in the diagram. What could we add to the module‐info.java in com.duck to allow the com.park module to reference the Duckling class but not allow the com.bread module to do the same?
![](https://i.imgur.com/Q0quV4k.png)
![](https://i.imgur.com/yrj0pYZ.png)
![](https://i.imgur.com/wPRrPGM.png)


### 概念题目，集中记忆5 command
![](https://i.imgur.com/JLw7B2C.png)
![](https://i.imgur.com/e2SsOfv.png)
![](https://i.imgur.com/2iiNXHp.png)
![](https://i.imgur.com/gDIUTXf.png)

![](https://i.imgur.com/zLTlbeJ.png)
![](https://i.imgur.com/pgCnUpX.png)
![](https://i.imgur.com/UJEnjlw.png)
![](https://i.imgur.com/VTS5zK0.png)
![](https://i.imgur.com/yOmwh0l.png)
![](https://i.imgur.com/UDgG9fv.png)
![](https://i.imgur.com/GfzouFU.png)
![](https://i.imgur.com/3Vwq8ns.png)
![](https://i.imgur.com/8MjVslN.png)












### top‐down migration AND bottom‐up migration
a top‐down migration starts by moving all the modules to the module path as automatic modules. Then, the migration changes each module from an automatic module to a named module。
![](https://i.imgur.com/ff1C38r.png)
![](https://i.imgur.com/6G8E41F.png)
![](https://i.imgur.com/E893b5y.png)
![](https://i.imgur.com/O2LKpBZ.png)
![](https://i.imgur.com/OnOG1Wo.png)










### 错题库
2，3，8-9-10-11-12（记忆重要），13-14(一起记忆)，16(多看)，17-18-19(重要)，21-22-23-25-26（概念题、记忆），24-20-27-30-32-36（一起看），28（优先看，记忆题），31，42





## 第八章Concurrency
### Java 多线程编程
基础知识：https://www.runoob.com/java/java-multithreading.html
![](https://i.imgur.com/phnWmBm.png)

Runnable接口有个问题，它的方法没有返回值。如果任务需要一个返回结果，那么只能保存到变量，还要提供额外的方法读取，非常不便。所以，Java标准库还提供了一个Callable接口（call()），和Runnable接口(run())比，它多了一个返回值：



#### 一文秒懂 Java ExecutorService
https://www.twle.cn/c/yufei/javatm/javatm-basic-executorservice.html
ExecutorService 是 Java java.util.concurrent 包的重要组成部分，是 Java JDK 提供的框架，用于简化异步模式下任务的执行。

一般来说，ExecutorService 会自动提供一个线程池和相关 API，用于为其分配任务。

总结：
* ExecutorService 可以执行 Runnable 和 Callable 任务。
* 创建完了任务之后，就可以使用多种方法将任务分配给 ExecutorService ，比如 execute() 方法，还有 submit()、invokeAny() 和 invokeAll() 等方法。这些方法都继承自 Executor 接口。
#### 一般方法
##### execute()
注意：只能执行Runnable任务
![](https://i.imgur.com/xSafDJN.png)

![](https://i.imgur.com/SQfApsV.png)

##### submit()

![](https://i.imgur.com/Sv5ODnp.png)

##### invokeAny()
![](https://i.imgur.com/Uj0Qjjd.png)


##### invokeAll()
![](https://i.imgur.com/or2TGDl.png)

题目：
![](https://i.imgur.com/iuZV0Yc.png)
![](https://i.imgur.com/AlhQecn.png)


#### 关闭方法
![](https://i.imgur.com/EccPU0c.png)

##### shutdown()
![](https://i.imgur.com/HnimxxE.png)

##### shutdownNow()
![](https://i.imgur.com/PwtsDrA.png)
![](https://i.imgur.com/v6hAnSz.png)

##### awaitTermination()
![](https://i.imgur.com/JltazXo.png)

##### submit()



#### Executors的静态方法
![](https://i.imgur.com/MF44jnF.png)



#### 使用Future(初步)
https://www.liaoxuefeng.com/wiki/1252599548343744/1306581155184674
```java=
ExecutorService executor = Executors.newFixedThreadPool(4); 
// 定义任务:
Callable<String> task = new Task();
// 提交任务并获得Future:
Future<String> future = executor.submit(task);
// 从Future获取异步执行返回的结果:
String result = future.get(); // 可能阻塞
```
当我们提交一个Callable任务后，我们会同时获得一个Future对象，然后，我们在主线程某个时刻调用Future对象的get()方法，就可以获得异步执行的结果。在调用get()时，如果异步任务已经完成，我们就直接获得结果。如果异步任务还没有完成，**那么get()会阻塞**，直到任务完成后才返回结果
![](https://i.imgur.com/AypxzpF.png)

注意如果是Runnable任务会返回NULL，因为Runnable没有返回值。
![](https://i.imgur.com/cZYJc69.png)



### ReentrantLock 可重入锁
公平锁和非公平锁，这篇文章写得非常好。
https://blog.csdn.net/JMW1407/article/details/122615690

知识点补充：
并发编程之原子性、可见性、有序性的简单理解：
https://www.cnblogs.com/shamo89/p/9069289.html

#### Lock的通用方法
https://blog.csdn.net/u011669700/article/details/80069097
![](https://i.imgur.com/py5PmUF.png)

题目：
![](https://i.imgur.com/ii4aKz5.png)


### CyclicBarrier 的理解和使用
https://hasaik.com/posts/6d42a1fc.html
CyclicBarrier 是一个同步辅助类，它允许一组线程互相等待，直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程程序中，这些线程必须不时地互相等待，此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用，所以称它为循环的 barrier 。

举个例子，就像生活中我们会约朋友们到某个餐厅一起吃饭，有些朋友可能会早到，有些朋友可能会晚到，但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程，餐厅就是 CyclicBarrier 。

题目：
![](https://i.imgur.com/XTn7RzQ.png)
![](https://i.imgur.com/PYGgyku.png)
![](https://i.imgur.com/jVOuQ9B.png)
![](https://i.imgur.com/S0OxDKj.png)




### 深入理解ConcurrentModificationException并发修改异常
https://blog.csdn.net/qq_42107430/article/details/105153433
![](https://i.imgur.com/wO2SusH.png)
![](https://i.imgur.com/pn9LHkB.png)



### 一起记忆1
![](https://i.imgur.com/xEIFZqU.png)
![](https://i.imgur.com/tgLxuxJ.png)
![](https://i.imgur.com/V9TdbBw.png)
![](https://i.imgur.com/wpP8AXr.png)

### 一起记忆2 锁相关
![](https://i.imgur.com/yLSrPfq.png)
![](https://i.imgur.com/pOnvMxr.png)

![](https://i.imgur.com/ug8eH7q.png)
![](https://i.imgur.com/ODmW5CK.png)

### 一起记忆3
![](https://i.imgur.com/eLH6xsF.png)
![](https://i.imgur.com/nxk3kPI.png)
![](https://i.imgur.com/6s3IlNY.png)





### 错题库
1,4，8（看！），13，14（记忆），17（必看synchronized(this)一定要带对象），23（记忆），




## 第九章Java I/O API
### Paths,Path,File常用方法
| 方法 | 描述 | 
| :---- | :---- | 
|Paths.get(URI uri)|返回一个Path对象|
|Path.of(URI uri)|Returns a Path by converting a URI.|
|Path.of(String first, String... more)|Returns a Path by converting a path string, or a sequence of strings that when joined form a path string.|



| Files方法 | 描述 | 返回|
| :---- | :---- | :----|
|createDirectory(Path dir, FileAttribute<\?\>... attrs\)|Creates a new directory.|Path|
|	createDirectories(Path dir, FileAttribute<\?>... attrs\)|Creates a directory by creating all nonexistent parent directories first.|Path|
|	delete(Path path)|Deletes a file.|void|
|copy(Path source, Path target, CopyOption... options)|Copy a file to a target file.|Path|
|walk（Path p, int maxDepth ）|限制搜索的层数，maxDepth表示最多到从当前算，往下多少层,Integer.MAX_VALUE是default|Path|


题目：
![](https://i.imgur.com/DIw0VeN.png)


题目walk：
![](https://i.imgur.com/anJrWyo.png)

题目find：
![](https://i.imgur.com/2PeEReU.png)

题目walk and find：
![](https://i.imgur.com/osrZFcE.png)

题目lines() and readAllLines()：
![](https://i.imgur.com/tUKkw1z.png)


#### Path.normalize()
https://vimsky.com/zh-tw/examples/usage/path-normalize-method-in-java-with-examples.html
此方法返回結果路徑；如果該路徑不包含冗餘名稱元素，則返回此路徑；否則，返回此路徑。如果此路徑沒有根組件並且所有名稱元素都是冗餘的，則返回一個空路徑。
![](https://i.imgur.com/dtHVj9k.png)

题目
![](https://i.imgur.com/iNO6eqt.png)
![](https://i.imgur.com/YaoO9ZL.png)






#### 重点方法Path.resolve
https://juejin.cn/post/6844903861920989198
path.resolve:方法会把一个路径或路径片段的序列解析为一个绝对路径。 例如
用法，path1.resolve(path2)
![](https://i.imgur.com/NBZwZ31.png)
![](https://i.imgur.com/iDrSoTo.png)

题目
![](https://i.imgur.com/QPqXZWh.png)

#### 重点方法Path.relativize
https://blog.csdn.net/king__12/article/details/114687494
![](https://i.imgur.com/ZvtpJiU.png)

The relativize() method requires that both path values be absolute or relative.
![](https://i.imgur.com/kSkASVd.png)





### forward backward
个人理解：
* forward：比如说/forward，这里的forward可以是下图中的java也可以是object
* backward：同理可得，./backward/forward这里的backward就是指的/，根目录。

![](https://i.imgur.com/fpbbFdH.png)
![](https://i.imgur.com/TwxcKNE.png)







### StandardCopyOption
https://www.cnblogs.com/zimug/p/13599866.html
#### StandardCopyOption.REPLACE_EXISTING
```java=
//如果目标文件存在就替换它
Files.copy(fromFile, toFile, StandardCopyOption.REPLACE_EXISTING);
```

#### StandardCopyOption.COPY_ATTRIBUTES
copy文件的属性，最近修改时间，最近访问时间等信息，不仅copy文件的内容，连文件附带的属性一并复制
```java=
CopyOption[] options = { StandardCopyOption.REPLACE_EXISTING,
      StandardCopyOption.COPY_ATTRIBUTES //copy文件的属性，最近修改时间，最近访问时间等
};
Files.copy(fromFile, toFile, options);
```

#### StandardCopyOption.ATOMIC_MOVE
Move the file as an atomic file system operation。
也可以指定使用原子方式來執行移動操作，這樣要麽移動操作成功完成，要麽源文件依然存在，可以使用StandardCopyOption.ATOMIC_MOVE選項

题目：
![](https://i.imgur.com/tDASGdB.png)
![](https://i.imgur.com/8lbFZ29.png)


### Java中console类的简单用法
https://www.cnblogs.com/-wanglei/p/10374673.html
首先，Console类只有private的构造器，所以它不可以通过new创建，只能用System.console();
其次，Java.io.Console 只能用在标准输入、输出流未被重定向的原始控制台中使用，在 Eclipse 或者其他 IDE 的控制台是用不了的。
例子：
![](https://i.imgur.com/I9BYryj.png)

题目：
![](https://i.imgur.com/Qk5m7et.png)
![](https://i.imgur.com/JcvwvEE.png)


### System.out.println与System.err.println的区别
https://blog.csdn.net/u014753393/article/details/49259215
![](https://i.imgur.com/Z9TMDoq.png)

题目：和上面讲的东西没有关系
![](https://i.imgur.com/69cyb9S.png)


### Serializable
https://zhuanlan.zhihu.com/p/40462507
把对象转化为可传输的字节序列过程称为序列化。
![](https://i.imgur.com/0Nji6J4.png)
![](https://i.imgur.com/Z3pHxG2.png)
![](https://i.imgur.com/156Amt3.png)

题目
![](https://i.imgur.com/mwmvha0.png)

![](https://i.imgur.com/lMtS6He.png)


![](https://i.imgur.com/bbjGDT4.png)
![](https://i.imgur.com/5eW0q4W.png)

![](https://i.imgur.com/tJWsmr9.png)



### InputStream接口
https://www.jianshu.com/p/2e92c69d8ae7
![](https://i.imgur.com/gTtejEB.png)
![](https://i.imgur.com/jGzSIC6.png)
题目：
![](https://i.imgur.com/hQGMXb0.png)

### NIO
#### 同步，异步，阻塞，非阻塞
同步和异步关注的是消息通信机制.

**同步**是指: 发送方发出数据后, 等待接收方发回响应后才发下一个数据包的通讯方式. 就是在发出一个调用时, 在没有得到结果之前, 该调用就不返回, 但是一旦调用返回, 就得到返回值了. 也就是由"调用者"主动等待这个"调用"的结果.

**异步**是指: 发送方发出数据后, 不等待接收方发回响应, 接着发送下个数据包的通讯方式. 当一个异步过程调用发出后, 调用者不会立刻得到结果. 而是在调用发出后, "被调用者"通过状态、通知来通知调用者, 或通过回调函数处理这个调用.

阻塞和非阻塞属于进程API执行动作的方式, 关注的是程序在等待调用结果时的状态.

**阻塞**是指: 调用结果返回之前, 当前线程会被挂起. 函数只有在得到结果之后才会返回, 线程需要等待结果.

**非阻塞**是指: 与阻塞的概念相对应, 指在不能立刻得到结果之前, 该函数不会阻塞当前线程, 而会立刻返回. 线程不需要等待结果.
https://cloud.tencent.com/developer/article/1525359#:~:text=%E5%90%8C%E6%AD%A5%E6%98%AF%E6%8C%87%3A%20%E5%8F%91%E9%80%81%E6%96%B9,%E6%95%B0%E6%8D%AE%E5%8C%85%E7%9A%84%E9%80%9A%E8%AE%AF%E6%96%B9%E5%BC%8F.

#### Nio理解（有点难理解）
相关阅读（全）：
https://www.cnblogs.com/czwbig/p/10056126.html
我们知道，一个新技术的出现总是伴随着改进和提升，Java NIO的出现亦如此。

传统 I/O 是阻塞式I/O，主要问题是系统资源的浪费。比如我们为了读取一个TCP连接的数据，调用 InputStream 的 read() 方法，这会使当前线程被挂起，直到有数据到达才被唤醒，那该线程在数据到达这段时间内，占用着内存资源（存储线程栈）却无所作为，也就是俗话说的占着茅坑不拉屎，为了读取其他连接的数据，我们不得不启动另外的线程。在并发连接数量不多的时候，这可能没什么问题，然而当连接数量达到一定规模，内存资源会被大量线程消耗殆尽。另一方面，线程切换需要更改处理器的状态，比如程序计数器、寄存器的值，因此非常频繁的在大量线程之间切换，同样是一种资源浪费。

随着技术的发展，现代操作系统提供了新的I/O机制，可以避免这种资源浪费。基于此，诞生了Java NIO，NIO的代表性特征就是非阻塞I/O。紧接着我们发现，简单的使用非阻塞I/O并不能解决问题，因为在非阻塞模式下，read()方法在没有读取到数据时就会立即返回，不知道数据何时到达的我们，只能不停的调用read()方法进行重试，这显然太浪费CPU资源了，从下文可以知道，Selector组件正是为解决此问题而生
https://segmentfault.com/a/1190000017040893

#### NIO与IO
**NIO vs IO**
学习了NIO之后我们都会有这样一个疑问：到底什么时候该用NIO，什么时候该用传统的I/O呢？

其实了解他们的特性后，答案还是比较明确的，NIO擅长1个线程管理多条连接，节约系统资源，但是如果每条连接要传输的数据量很大的话，因为是同步I/O，会导致整体的响应速度很慢；而传统I/O为每一条连接创建一个线程，能充分利用处理器并行处理的能力，但是如果连接数量太多，内存资源会很紧张。

总结就是：连接数多数据量小用NIO，连接数少用I/O（写起来也简单- -）。

#### NIO2
NIO是**同步非阻塞**，NIO2是**异步阻塞**
客户端一个IO请求对应一个线程。过程同NIO，只是在读写IO时略有差异，对于read，方法调用后会立即返回，返回对应中有个回调方法，调用时java会告知操作系统缓冲区大小以及地址，操作系统把流里面的内容读入缓冲区后回调刚刚read返回的回调方法。对应write，方法调用后会立即返回，返回对应中有个回调方法，调用时将数据放入缓存区，操作系统往流里面写完数据后同样会回调刚刚wirte返回的回调方法。阻塞是因为此时是通过select系统调用来完成的，而select函数本身的实现方式是阻塞的，而采用select函数有个好处就是它可以同时监听多个文件句柄，从而提高系统的并发性请求。异步步体现在单个线程处理请求时调用read（write）方法会立即返回，返回对象有回调方法，底层OS完成IO操作后会回调该方法。

#### BIO,NIO,AIO(NIO2)的理解
https://www.cnblogs.com/reboot30/p/8252109.html
BIO（同步并阻塞）
NIO（同步非阻塞）
AIO(NIO2)（异步阻塞）

**适用场景**：

* BIO方式适用于连接数目比较小且固定的架构，这种方式对服务器资源要求比较高，并发局限于应用中，JDK1.4以前的唯一选择，但程序直观简单易理解。
* NIO方式适用于连接数目多且连接比较短（轻操作）的架构，比如聊天服务器，并发局限于应用中，编程比较复杂，JDK1.4开始支持。
* AIO方式使用于连接数目多且连接比较长（重操作）的架构，比如相册服务器，充分调用OS参与并发操作，编程比较复杂，JDK7开始支持。


题目：
![](https://i.imgur.com/aZ3sTIu.png)


### 集中记忆1
![](https://i.imgur.com/AwEtEvp.png)
![](https://i.imgur.com/LGpfYtK.png)
![](https://i.imgur.com/4nWKNXm.png)
![](https://i.imgur.com/ciLfvNf.png)
![](https://i.imgur.com/UofmzrM.png)
![](https://i.imgur.com/GHEQsbd.png)
![](https://i.imgur.com/sQ8wEwU.png)
![](https://i.imgur.com/PdNd7Ks.png)




### 错题库
3（绝了，一定要多看），7，9（看）,13，23(看)，26，






## 第十章Secure Coding in Java SE Application
### Serializable相关
![](https://i.imgur.com/hZLJU98.png)
![](https://i.imgur.com/up62KF9.png)
![](https://i.imgur.com/oq5mhx2.png)

#### serialPersistentFields
获取实现Serializable接口的对象的字段，（实现Externalizable的为空字段），先获取声明的private static final ObjectStreamField[] serialPersistentFields，它的规则是“声明指定要序列化的字段必须类型和名字要和实际的对应，且不能是static字段”，如果未声明就去获取默认的序列化字段（就是除了static和transient修饰的其他字段）。换句话说如果声明了这个字段，就不会去序列化类中的属性字段；

题目：
![](https://i.imgur.com/o6Yjc5s.png)


#### 自定义序列化customizing the serialization
https://www.jianshu.com/p/352fa61e0512
![](https://i.imgur.com/f0knyH9.png)

简单概括下，不要轻易的决定将一个类序列化”，所以在没有十分明确的需求下，不要轻易将School类改为“ implements Serializable”，否则School类如果以后被修改，将会影响到Student类序列化的格式，我们在设计类的序列化格式时最重要的原则就是保持其字节化格式的固定性，以降低维护它的代价。
那么这种时候我们又想序列化School中的某些属性，那么就用到这个自定义序列化。
![](https://i.imgur.com/3NDxj8G.png)
例子：
![](https://i.imgur.com/KBiXnsi.png)


题目：
![](https://i.imgur.com/4k4xofP.png)



### SQL安全相关
#### SQL Injection: 
https://www.cnblogs.com/lsdb/p/9612424.html
![](https://i.imgur.com/PRRwptJ.png)

题目：
![](https://i.imgur.com/wiFTsrX.png)

题目：
![](https://i.imgur.com/S12KVaI.png)
理解：var ps = con.createStatement();因为它可能会出错，所以一旦它出错了，又没有写进try‐with‐resources block里，那么就会导致con无法关闭。

题目：
![](https://i.imgur.com/10AyI9h.png)
题目：
![](https://i.imgur.com/I62qwcK.png)
题目：
![](https://i.imgur.com/rcyhBBr.png)






### 攻击总结（除SQL相关）
#### DOS攻击：
https://zhuanlan.zhihu.com/p/79201759
DoS是Denial of Service的简称，即拒绝服务，造成DoS的攻击行为被称为DoS攻击，其目的是使计算机或网络无法提供正常的服务。最常见的DoS攻击有计算机网络宽带攻击和连通性攻击。
![](https://i.imgur.com/zWV8UaW.png)
![](https://i.imgur.com/ky7ASS7.png)


题目：
![](https://i.imgur.com/7EwC6Fr.png)
![](https://i.imgur.com/IuMwf4b.png)
![](https://i.imgur.com/oERFyil.png)
![](https://i.imgur.com/ta5yF65.png)
![](https://i.imgur.com/818vdbC.png)



#### DDOS攻击：
分布式拒绝服务攻击(英文意思是Distributed Denial of Service，简称DDoS)是指处于不同位置的多个攻击者同时向一个或数个目标发动攻击，或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。由于攻击的发出点是分布在不同地方的，这类攻击称为分布式拒绝服务攻击，其中的攻击者可以有多个。
![](https://i.imgur.com/Dc94BG3.png)
![](https://i.imgur.com/qzafb4S.png)

题目：
![](https://i.imgur.com/lvs5NBh.png)



#### inclusion attacks
https://blog.51cto.com/wt7315/1863177
![](https://i.imgur.com/YV9b4xo.png)
![](https://i.imgur.com/iCdFviU.png)
![](https://i.imgur.com/IBrbA9K.png)



### java.policy 文件格式及使用方法（grant ）
https://www.cnblogs.com/dongzhiquan/archive/2010/09/26/1994546.html
![](https://i.imgur.com/emwnOQH.png)
![](https://i.imgur.com/EXZJzRT.png)
例子：
![](https://i.imgur.com/tdOM5fu.png)


题目：
![](https://i.imgur.com/l0K9Pw1.png)
题目：
![](https://i.imgur.com/1TzTHPF.png)



### 记忆一起

![](https://i.imgur.com/uJSTTyn.png)
重要！！2
![](https://i.imgur.com/0RXOocf.png)
![](https://i.imgur.com/MBpTppM.png)





### 记忆一起2
![](https://i.imgur.com/mUn4ELL.png)
![](https://i.imgur.com/ka4gq3I.png)
![](https://i.imgur.com/GGqA3Km.png)
![](https://i.imgur.com/XsRBmcq.png)
![](https://i.imgur.com/hmCZ5ga.png)

### 记忆一起3 immutable
![](https://i.imgur.com/AxY9mdM.png)
![](https://i.imgur.com/6USW1gD.png)
![](https://i.imgur.com/dc1WRDR.png)




### 记忆一起4 Clone
![](https://i.imgur.com/nyk1qEG.png)
理解：如果是浅copy，它只是copy它的索引，如果是深copy，那么就会重新创建一个对象，copy除了地址以外所有东西。而且如果该class如果没有implements Cloneable，那么就只能等于Object对象，不能强制转换成目前的class。
![](https://i.imgur.com/KeEq02x.png)


### 错题库
8（记忆），




## 第十一章Database Applications with JDBC
这章属于基础章节了，实习过或者工作过的都多多少少会些。


### 一起记忆
![](https://i.imgur.com/hDn2oXq.png)

![](https://i.imgur.com/XpMEy5O.png)
![](https://i.imgur.com/26OudDT.png)
![](https://i.imgur.com/yreFk7S.png)
因为executeQuery()要返回ResultSet对象，所以不能用与Delete或者Update
![](https://i.imgur.com/V6igsdQ.png)
![](https://i.imgur.com/QLQLYCg.png)

![](https://i.imgur.com/Mspk00l.png)
![](https://i.imgur.com/yLUtbv7.png)
![](https://i.imgur.com/GewxJnl.png)



### 一起记忆2
![](https://i.imgur.com/H8gV24o.png)
注意：ResultSet 中都是get**基础数据类型**和String
![](https://i.imgur.com/Gf6YSUF.png)
![](https://i.imgur.com/OqOTqFA.png)
![](https://i.imgur.com/omGo2FJ.png)
![](https://i.imgur.com/LSZnVF8.png)

### 一起记忆3
![](https://i.imgur.com/yg10hbc.png)

### 一起记忆4
![](https://i.imgur.com/Q6E1PXy.png)
![](https://i.imgur.com/pRTt3yq.png)








### 错题库


## 第十二章Localization
这个也不难
### 概念
大概就是，在不同的地区用不用的标准（这个标准可能包括：字体（繁体、简体），时区等）
![](https://i.imgur.com/jvNYSSv.png)

![](https://i.imgur.com/eLHpnLO.png)
#### Category.FORMAT and Category.DISPLAY
![](https://i.imgur.com/QO7ehFw.png)
![](https://i.imgur.com/7Gbd55G.png)

### 必会题
这算是这个章节里最重要的题目了。其他题目也是这么考察的，大差不差。
一开始检查Colors_fr.properties,发现没有，再去检查default的配置文件Colors_en_US.properties，如果再没有，就找Colors_en.properties，Colors.properties再没有就报错。
![](https://i.imgur.com/E9HUSVO.png)


2. 不一样的地方，对上面的一点补充，如果Colors_en.properties中有**变量**，记住一定是变量找不到的情况，才会继续往下找，去Colors.properties里找是否有相应的变量存在。
![](https://i.imgur.com/pRG32Nr.png)
![](https://i.imgur.com/R8iHoDY.png)


3. 如果期间找到了，比如找到了Colors_fr_FR.properties,那么它就不会再去找default了，相对应的会去找Colors_fr.properties和Colors.properties中的变量！！注意是变量！！
![](https://i.imgur.com/IvzMJA4.png)

![](https://i.imgur.com/UwFjmGa.png)

![](https://i.imgur.com/62djWaR.png)
![](https://i.imgur.com/8fTd7Ke.png)
![](https://i.imgur.com/aeA4v9X.png)



#### 又一道坑爹题
注意这里，它找到Forest.properties
![](https://i.imgur.com/uSFVtuM.png)









### DateTimeFormatter
https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
不用全记，眼熟就行
![](https://i.imgur.com/07QGLAG.png)

题目：
![](https://i.imgur.com/fjCfPYp.png)
题目：
![](https://i.imgur.com/K9nBPe4.png)
题目：陷阱题！！！！！！
![](https://i.imgur.com/5CixMjk.png)
多看
![](https://i.imgur.com/bV3nUsW.png)





### Properties 
https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
记忆两个方法
![](https://i.imgur.com/LBAriBS.png)
![](https://i.imgur.com/qv8p4w0.png)

![](https://i.imgur.com/sccvpZl.png)



### DecimalFormat数字相关
\#表示任意，有多少个都不表示强制要求有多少，至少一个
0表示强制，有多少个0就代表这里要占多少位置
看下面题来理解
![](https://i.imgur.com/DDqzNX6.png)


### 概念记忆
![](https://i.imgur.com/MtlaRRi.png)
![](https://i.imgur.com/SJFOgl6.png)
![](https://i.imgur.com/ifGpBI8.png)













### 错题库






## 第十三章 Annotations
有点难的
基础概念： https://www.runoob.com/w3cnote/java-annotation.html

### 秒懂，Java 注解 （Annotation）你可以这样学
标题很狂的文章，但是确实秒懂
https://zhuanlan.zhihu.com/p/27643133
![](https://i.imgur.com/kFMnBC8.png)
![](https://i.imgur.com/8OKSHrD.png)
![](https://i.imgur.com/egUijtN.png)
![](https://i.imgur.com/uvEO0Mi.png)
![](https://i.imgur.com/oWUE3pL.png)
![](https://i.imgur.com/VhgjfZ9.png)
![](https://i.imgur.com/4wUMx5o.png)
![](https://i.imgur.com/13vASxU.png)
![](https://i.imgur.com/AJUnATg.png)
继续阅读请看上面的文章



题目：![](https://i.imgur.com/Qdj6BoW.png)
![](https://i.imgur.com/UGaIays.png)


题目：可以用的 element type
An annotation element type must be a primitive type, a String, a Class, an enum, another annotation, or an array of any of these types. 
![](https://i.imgur.com/m2av8Xp.png)

题目：@Repeatable
![](https://i.imgur.com/6Y0szwN.png)
![](https://i.imgur.com/E0aJyDg.png)


题目：@SafeVarargs
忽略任何使用参数为**泛型变量的方法**或**构造函数**调用产生的警告and be unable to be **overridden**！！
![](https://i.imgur.com/V4yWEfW.png)

题目：关于规则
![](https://i.imgur.com/pwPocyL.png)


题目：@FunctionalInterface 
标识一个匿名函数或函数式接口。
![](https://i.imgur.com/aWhg4F9.png)
![](https://i.imgur.com/PHbXWPI.png)




#### 一些容易忽略的规则
1. 注解不能用包装类
![](https://i.imgur.com/djLS8Po.png)





### annotation 与 interface
![](https://i.imgur.com/QcST7oY.png)

### SuppressWarnings() 括号里必要有参数nchecked/unsafe/deprecation
阻止警告的意思。之前说过调用被 @Deprecated 注解的方法后，编译器会警告提醒，而有时候开发者会忽略这种警告，他们可以在调用的地方通过 @SuppressWarnings 达到目的
作用于Class和Method，不作用于variable
![](https://i.imgur.com/3Y0X9O0.png)
![](https://i.imgur.com/ON6ZOLo.png)


### marker annotations
marker annotations： they do not contain any elements
![](https://i.imgur.com/zeoR8Z3.png)


### 有些难度的题目
因为接口的变量都是默认为public static final 的，方法public abstract。而annotation与接口是类似的。
![](https://i.imgur.com/6tOPpn9.png)


![](https://i.imgur.com/6ZhDXSS.png)


多看就完事儿了
![](https://i.imgur.com/FPNWgJB.png)
![](https://i.imgur.com/Q7r1kUI.png)



### 一起记忆
![](https://i.imgur.com/lnXvP8o.png)
![](https://i.imgur.com/WsWSRlS.png)





## Java variable type
### String
#### 1. String.intern()
String的intern()方法是查询当前字符串是否在常量池中，如果不在则把当前的字符串内容放到**常量池（heap）**中。
**扩展：** String对象放入常量池的方法
1. 创建String的时候不要用new，用双引号“”
```java=
String s1 = new String("abc");//Object, save in the stack
String s2 = "abc";// Constant, save in Constant Pool Table

System.out.println(s1 == s2); // false
```
![](https://i.imgur.com/4Px11T7.png)
picture from：https://www.jianshu.com/p/75c539eaab5a
2. 使用String.intern()
```java=
System.out.println(s1 == s2.intern()); //true
```

#### 2. literal strings
了解创建String对象时，何时会在常量池中创建，何时会在堆（stack）上创建。
原文地址：https://zhuanlan.zhihu.com/p/86004644
```java=
String s1 = "ss";       // 在常量池上创建常量s1
String s2 = "ss";       // 直接放回已存在的常量
System.out.println(s1 == s2);   // true
String s1 = new String("ss");   // 在堆上创建对象
String s2 = new String("ss");   // 在堆上创建对象
System.out.println(s1 == s2);   // false
String s1 = "ss1" + "ss2"   // 在常量池上创建常量ss1、ss2、ss1ss2
String s2 = "ss1ss2";
String s3 = "ss1" + "ss2";
System.out.println(s2 == s3);  // true
String s1 = new String("ss1") + new String("ss2");  // 在堆上创建对象ss1、ss2和ss1ss2，在常量池上创建常量ss1和ss2
s1.intern();
String s2 = "ss1" + "ss2";
System.out.println(s1 == s2);   // true
String s1 = new String("ss") + new String("ss1");   // 常量ss不存在，所以第一步在常量池中创建了常量ss
String s2 = new String("s") + new String("s");  // 创建对象ss
System.out.println(s2 == s2.intern());      // false
System.out.println(s1 == s1.intern());      // true
String s1 = "ss1ss2";
String s2 = "ss1" + new String("ss2");
System.out.println(s1 == s2.intern());      // true
String s1 = "ss1ss2";
String s2 = "ss1" + new String("ss2");
System.out.println(s1 == s2.intern());      // true
System.out.println(s2 == s2.intern());      // false
```

***难点解释***：
1. 关于 +
```java=
String s1 = new String("ss1") + new String("ss2");
String s2 = "ss1" + new String("ss2");
```
不管是两个String Object想连还是一个String Constants和一个String Object相连，底层的logic都是用的StringBuilder.append()方法。官方文档说了，append方法返回的是一个“**a reference to this object**”，返回的是一个Object的地址，而Object的地址存在于Heap中。

StringBuilder_append_Documentation:https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StringBuilder.html#append(boolean)

2. 关于intern()
如果String.intern()能够在String pool里找到相应的内容，那么就会返回String pool中内容的地址，如果String pool中没有相应的内容，那么就会首先创建在String pool中创建一个内容“***常量***”，并且让Stack中的变量直接指向String pool中的地址，而“***放弃***”指向Heap中Object的地址。那么一段时间后，这个Object因为没有变量指向，就会被java的garbage collection机制回收。**这样可以节省内存。**

3. 难题解释
这里面最难理解的一题应该是这一道
```java=
String s1 = new String("ss") + new String("ss1");   // 常量ss不存在，所以第一步在常量池中创建了常量ss
String s2 = new String("s") + new String("s");  // 创建对象ss
System.out.println(s2 == s2.intern());      // false
System.out.println(s1 == s1.intern());      // true
```
解析：
case1：
![](https://i.imgur.com/iozoiae.jpg)
```java=
String s1 = new String("ss") + new String("ss1"); 
// 这个语句的执行流程，首先在heap中创建一个object“ss”, 发现String pool
// 中没有“ss”常量，所以在String pool中创建常量“ss”，创建“ss1”的过程一样。
// 然后两个匿名对象通过“+”相连，返回一个新对象的“ssss1”对象的地址给在Heap中的s1。

String s2 = new String("s") + new String("s");
// 与上面类似，最后s2指向Obejct"ss"的地址
// （需要注意的是，这个oject"ss"和上面说的那个object"ss"不是一个东西，也就是说是两个独立的个体，地址不同）

System.out.println(s2 == s2.intern());
// s2指向object"ss", s2.intern()首先会去String pool中寻找是否有“ss”存在，
// 发现存在，那么就会返回String pool中"ss"的地址，所以两个地址不同，返回false

System.out.println(s1 == s1.intern());
// s1指向object"ssss1", s1.intern()首先会去String pool中寻找是否有“ssss1”存在，
// 发现没有，所以首先在常量池中创建对Heap中S1对象的引用，所以返回true。
```
case2：
大家可以试试这个题：
```java=
String s2 = new String("s") + new String("s");
System.out.println(s2 == s2.intern()); // true
```
![](https://i.imgur.com/EKt1uOV.jpg)


#### String concat
源码阅读：https://blog.csdn.net/m0_38039437/article/details/95165174
简单描述就是，使用concat连接的两个字符最后会返回一个String Object。

### var （java 10 new feature）
相关阅读：https://www.infoq.cn/article/java-10-var-type-inference
## Chapter 6: Working with Streams and Lambda Expressions
### 对Steam的浅显解释
https://blog.csdn.net/u011001723/article/details/52794455


## I/O
### Path.resolve()
16题
https://blog.csdn.net/iconhot/article/details/89257576

## Annotation
https://zhuanlan.zhihu.com/p/27643133

## Exam1
### java try-with-resource语句使用
java try-with-resource语句使用
https://blog.csdn.net/absolute_chen/article/details/100889727

深入理解Java try-with-resource 
https://zhuanlan.zhihu.com/p/27824934

总结起来就是，我们可以在try(){}的小括号里写语句了，这里写的语句（对象）必须实现了AutoCloseable，或者Closeable。这样在执行完try之后，就会自动close()连接，尤其方便用在一些需要开/关连接的一些object上。






## Exam1
1. TODO: 这个还有些疑问,为什么用了parallel，它依旧能够保证findFirst()输出的1？（return Optional对象）
![](https://i.imgur.com/gAq338x.png)

2. 不能呼叫抽象类的方法，其次，Override的子方法的访问修饰符不能低于父类的。
![](https://i.imgur.com/AJIT42N.png)

3. 如果子类继承的父类已经有了一个构造器，且构造器带参数，那么子类如果没有构造器的情况下，会被编译器当作没有构造器。
如果子类和父类都有无参构造，那么创建子类的时候，会先使用父类的构造器，再运行子类的构造器。
![](https://i.imgur.com/4A0Mn38.png)





4. TODO: 应该有一道差不多的题
![](https://i.imgur.com/dMvwD74.png)

5. 比记
![](https://i.imgur.com/MNfwIeM.png)

6. 值得看
![](https://i.imgur.com/D8OT6HY.png)


7. 
![](https://i.imgur.com/lyXKNAX.png)



8.
![](https://i.imgur.com/i0L20DI.png)



## Exam2
 
1. 无参构造可以使用，带参数String的构造不可以用，这个很好理解，但是this(new Exception(s));也能用（只有它可以用），这个就无法理解。死记吧。
![](https://i.imgur.com/qVGU7e7.png)
![](https://i.imgur.com/vbyUNGk.png)

2. 暂时这么理解，所有都加锁的class都是线程安全的，其实不是应该是：期望结果等于程序运行结果就是线程安全的
![](https://i.imgur.com/ZrOuyNQ.png)

3. interface中的default使用
https://llongliu.github.io/2019/08/24/JAVA/1th-Basic/026-interface/#:~:text=%E6%8E%A5%E5%8F%A3%E4%B8%AD%E4%B8%80%E8%88%AC%E5%8F%AA%E8%83%BD,%E7%9A%84default%E5%85%B3%E9%94%AE%E5%AD%97%E4%BF%AE%E9%A5%B0%E3%80%82
这个地方的Plant.super.grow()确实需要死记，时间不够了。
![](https://i.imgur.com/UmB21xt.png)


Annotation中的abstract是允许使用的！！还有！!switch只接受short，char，int，byte（还有其他，不写了）！！！！！！！不接受long！浮点型！boolean！！！！！
![](https://i.imgur.com/PzJwuiw.png)


4. 这个下次真的不能错了，方法的命名和变量差不多
![](https://i.imgur.com/69hJYzk.png)


5. 震碎三观，this可以去呼叫static变量，还是合法的（仅限在构造器中）
![](https://i.imgur.com/Na5thQH.png)

6. 三元表达式ternary operator，重点记忆这个就可以了
![](https://i.imgur.com/m2YaDQg.png)

7. 光考虑方法可不可行了，没有考虑实际情况，文件一旦转移就没有办法再用了
![](https://i.imgur.com/HWUL7jr.png)

8. 纯记忆题，这个概念倒是第一次见
![](https://i.imgur.com/isQzUFx.png)

9. 记忆一下，如果碰见了之前复习的，记得一起再看多一次
![](https://i.imgur.com/K3DrVzK.png)


10. 学到了，Arrays.asList(T..)返回的是一个fixed-size的List,所以add或者revome都会出错
![](https://i.imgur.com/p5FHt71.png)

11. 记忆Command jdeps 
![](https://i.imgur.com/RPkOXww.png)

12. 多看看，有点像平时写程序的时候，我们会先写在interface中，然后interfaceImpl.class去实现它（Bean会调用他们）。所以要改方法参数的时候，会改动三个class。
![](https://i.imgur.com/UYS6QMe.png)

13. annotation的使用也就那么几个，多多记忆
![](https://i.imgur.com/kF8VDjg.png)

14. 这个需要记忆一下，这个题目问的是，以下什么方法可以通过“它们”的构造器创建。
![](https://i.imgur.com/sZdBuNd.png)

15. 这个题不应该错的
![](https://i.imgur.com/yJJsXXN.png)


16. 抽象类
https://www.jianshu.com/p/93d701282bd9
![](https://i.imgur.com/anRrxby.png)

![](https://i.imgur.com/fmNfIwT.png)



17. InputStream and Reader 记忆
![](https://i.imgur.com/aOO45ku.png)


18. inner class(nested classes)
![](https://i.imgur.com/Ij2X4v4.png)


19. accessor or mutator method，还用别的专门词汇来表达，搞得我一愣一愣的，妈的就是getter和setter
![](https://i.imgur.com/cBRClGV.png)
![](https://i.imgur.com/FhytEg5.png)





### 内部类总结
https://www.runoob.com/w3cnote/java-inner-class-intro.html
广泛意义上的内部类一般来说包括这四种：成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。
* 成员内部类：
1.成员内部类可以无条件访问外部类的所有成员属性和成员方法（包括private成员和静态成员）。
2.![](https://i.imgur.com/v4Pau4S.png)
3.![](https://i.imgur.com/mudZKis.png)

* 局部内部类
![](https://i.imgur.com/O0BqiJe.png)

* 匿名内部类 类似于实现conparator接口
![](https://i.imgur.com/i5RKT4Z.png)

* 静态内部类 理解成一个静态的成员就好
![](https://i.imgur.com/dFuFUj4.png)


### Default关键词总结
1.用在switch中
2.访问修饰符（不能在实体类中使用）
3.在接口中，抽象类中定义方法
4.函数式接口中default关键词表示（optional）


### 泛型中通配符？的总结
https://www.junhaow.com/2019/02/14/046%20%7C%20%E5%A5%BD%E5%A5%BD%E8%B0%83%E6%88%8F%20Java%20%E8%8C%83%E5%9E%8B%E4%B8%AD%E7%9A%84%E9%80%9A%E9%85%8D%E7%AC%A6%E4%BB%A5%E5%8F%8A%E8%BE%B9%E7%95%8C%E9%99%90%E5%AE%9A%E8%A7%84%E5%88%99/
![](https://i.imgur.com/vThiI90.png)


### java集合框架
https://www.runoob.com/java/java-collections.html
![](https://i.imgur.com/oD3ceFh.png)
总结：
treeMap和TreeSet是sorted（元素有序的）

### 单例模式
这篇文章真的写得非常好！！！
https://github.com/Ziphtracks/JavaLearningmanual/blob/master/docs/design-mode/01.%E5%8D%95%E4%BE%8B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md

### 枚举类讲解（强烈推荐，非常易懂）
https://www.cnblogs.com/ziph/p/13068923.html

### 一个关于lambda的总结
包含Lambda表达式，Collection,Steam,Map等新增方法的介绍和理解（必须阅读）
https://objcoding.com/2019/03/04/lambda/


