diff --git a/notes/Docker.md b/notes/Docker.md index 9fceb5ee..c67da0a8 100644 --- a/notes/Docker.md +++ b/notes/Docker.md @@ -36,7 +36,7 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程 虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU 资源,一台机器只能开启几十个的虚拟机。 -而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 +而容器只是宿主机上隔离运行的进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以运行成千上万个容器。 ## 三、优势 @@ -152,7 +152,7 @@ spec: 在单节点 K8s(k3s v1.31)上实际操作的结果如下: - kubectl apply 之后约 20 秒,3 个 Pod 全部就绪,Service 得到虚拟 IP 10.43.189.89,在集群内用 http://order-service 就能访问; -- 删除一个 Pod,Deployment 发现副本数少于 3,立即创建新的 Pod,约 1.2 秒后恢复为 3/3,新 Pod 的 IP 与原来不同,Service 自动更新了后端列表; +- 删除一个 Pod,Deployment 创建的 ReplicaSet 发现副本数少于 3,立即创建新的 Pod,约 1.2 秒后恢复为 3/3,新 Pod 的 IP 与原来不同,Service 自动更新了后端列表; - kubectl scale 把副本数改为 5;kubectl set image 修改镜像版本后,Deployment 创建新的 ReplicaSet,逐个用新版本的 Pod 替换旧的,约 12 秒完成滚动升级,期间一直有就绪的 Pod 在提供服务,需要时可以用 kubectl rollout undo 回滚。 readinessProbe 是就绪探针:Pod 启动后要通过检查才会加入 Service 的后端列表,避免把请求转发给还没启动完成的实例。 diff --git a/notes/Git.md b/notes/Git.md index e24d77df..356bfcf0 100644 --- a/notes/Git.md +++ b/notes/Git.md @@ -71,7 +71,7 @@ Git 的版本库有一个称为 Stage 的暂存区以及最后的 History 版本

-合并分支也只需要改变指针即可:切换回 master 后合并 dev,master 直接移动到 dev 所指的提交。 +合并分支也只需要改变指针即可:切换回 master 后合并 dev,master 直接移动到 dev 所指的提交。这种情况称为快进合并(Fast-forward),两个分支都有新的提交时,合并会生成一个新的提交。

@@ -105,9 +105,9 @@ $ git merge --no-ff -m "merge with no-ff" dev ## 储藏(Stashing) -在一个分支上操作之后,如果还没有将修改提交到分支上,此时进行切换分支,那么另一个分支上也能看到新的修改。这是因为所有分支都共用一个工作区的缘故。 +在一个分支上操作之后,如果还没有将修改提交到分支上,此时进行切换分支,那么另一个分支上也能看到新的修改。这是因为所有分支都共用一个工作区的缘故。如果这些修改涉及的文件在两个分支上不同,切换会覆盖掉修改,Git 会拒绝切换。 -可以使用 git stash 将当前分支的修改储藏起来,此时当前工作区的所有修改都会被存到栈中,也就是说当前工作区是干净的,没有任何未提交的修改。此时就可以安全的切换到其它分支上了。 +可以使用 git stash 将当前分支的修改储藏起来,此时当前工作区中已跟踪文件的修改都会被存到栈中,工作区回到干净的状态;未跟踪的新文件默认不会储藏,需要加上 -u 选项。此时就可以安全的切换到其它分支上了。 ```bash $ git stash @@ -119,15 +119,15 @@ HEAD is now at 049d078 added the index file (To restore them type "git stash app ## SSH 传输设置 -Git 仓库和 GitHub 中心仓库之间的传输是通过 SSH 加密。 +Git 仓库和 GitHub 中心仓库之间可以通过 HTTPS 或者 SSH 加密传输,使用 SSH 时需要配置 SSH Key。 -如果用户主目录下没有 .ssh 目录,或者该目录下没有 id_rsa 和 id_rsa.pub 这两个文件,可以通过以下命令来创建 SSH Key: +如果用户主目录下没有 .ssh 目录,或者该目录下没有 id_ed25519 和 id_ed25519.pub 这两个文件,可以通过以下命令来创建 SSH Key: ```bash -$ ssh-keygen -t rsa -C "youremail@example.com" +$ ssh-keygen -t ed25519 -C "youremail@example.com" ``` -然后把公钥 id_rsa.pub 的内容复制到 GitHub “Settings” 的 SSH Keys 中。 +然后把公钥 id_ed25519.pub 的内容复制到 GitHub “Settings” 的 SSH Keys 中。 ## .gitignore 文件 diff --git a/notes/Java IO.md b/notes/Java IO.md index 08be381f..ff25ad46 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -125,7 +125,7 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作, UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-16le,le 指的是 Little Endian,也就是小端。 -Java 的内存编码使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。 +Java 的 char 类型占 16 位,存放的是字符的 UTF-16 编码,这不是指 Java 只支持这一种编码方式。常用的中文和英文字符都能用一个 char 存储,编号超过 U+FFFF 的字符(例如一部分生僻字和 emoji)要用两个 char 表示。 ### String 的编码方式 @@ -138,7 +138,7 @@ String str2 = new String(bytes, "UTF-8"); System.out.println(str2); ``` -在调用无参数 getBytes() 方法时,默认的编码方式不是 UTF-16be。双字节编码的好处是可以使用一个 char 存储中文和英文,而将 String 转为 bytes[] 字节数组就不再需要这个好处,因此也就不再需要双字节编码。getBytes() 的默认编码方式与平台有关,一般为 UTF-8。 +在调用无参数 getBytes() 方法时,默认的编码方式不是 UTF-16。双字节编码的好处是可以使用一个 char 存储中文和英文,而将 String 转为 bytes[] 字节数组就不再需要这个好处,因此也就不再需要双字节编码。JDK 18 起 getBytes() 默认使用 UTF-8(JEP 400),之前的版本与平台有关。 ```java byte[] bytes = str1.getBytes(); @@ -254,7 +254,7 @@ InetAddress.getByAddress(byte[] address); ```java public static void main(String[] args) throws IOException { - URL url = new URL("http://www.baidu.com"); + URL url = URI.create("http://www.baidu.com").toURL(); /* 字节流 */ InputStream is = url.openStream(); diff --git a/notes/Linux.md b/notes/Linux.md index 2a89abf4..2b4ab715 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -228,7 +228,7 @@ SAS(Serial Attached SCSI)是新一代的 SCSI 技术,和 SATA 硬盘相同 Linux 中每个硬件都被当做一个文件,包括磁盘。磁盘以磁盘接口类型进行命名,常见磁盘的文件名如下: -- IDE 磁盘:/dev/hd[a-d] +- IDE 磁盘:/dev/hd[a-d](旧驱动的命名,Linux 5.14 移除了旧的 IDE 驱动,现在由 libata 驱动 IDE 磁盘,也命名为 /dev/sd*) - SATA/SCSI/SAS 磁盘:/dev/sd[a-p] - NVMe 磁盘:/dev/nvme0n1、/dev/nvme1n1 @@ -278,7 +278,7 @@ BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可 #### 2. UEFI -BIOS 不可以读取 GPT 分区表,而 UEFI 可以。 +BIOS 只会执行 MBR 中的开机管理程序,本身不读取分区表,从 GPT 磁盘启动要依靠支持 GPT 的开机管理程序(例如 GRUB);UEFI 可以直接读取 GPT 分区表。 ## 四、文件系统 @@ -450,7 +450,7 @@ rmdir [-p] 目录名称 ```text ## touch [-acdmt] filename -a : 更新 atime --c : 更新 ctime,若该文件不存在则不建立新文件 +-c : 若该文件不存在则不建立新文件 -m : 更新 mtime -d : 后面可以接更新日期而不使用当前日期,也可以使用 --date="日期或时间" -t : 后面可以接更新时间而不使用当前时间,格式为[YYYYMMDDhhmm] @@ -760,7 +760,7 @@ $ xz [-dtlkc#] filename $ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件] filename... ==打包压缩 $ tar [-z|-j|-J] [tv] [-f 已有的 tar 文件] ==查看 $ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件] [-C 目录] ==解压缩 --z :使用 zip; +-z :使用 gzip; -j :使用 bzip2; -J :使用 xz; -c :新建打包文件; @@ -785,7 +785,7 @@ $ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件] [-C 目录] ==解压缩 - 命令历史:记录使用过的命令 - 命令与文件补全:快捷键:tab -- 命令别名:例如 ll 通常是 ls -l 或者 ls -alF 的别名,具体取决于发行版的配置 +- 命令别名:例如 Ubuntu 默认的 ~/.bashrc 中,ll 是 ls -alF 的别名 - shell scripts - 通配符:例如 ls -l /usr/bin/X\* 列出 /usr/bin 下面所有以 X 开头的文件 diff --git a/notes/SQL 练习.md b/notes/SQL 练习.md index 464a8cfd..1f6b3355 100644 --- a/notes/SQL 练习.md +++ b/notes/SQL 练习.md @@ -764,7 +764,7 @@ VALUES ### Solution ```sql -CREATE FUNCTION getNthHighestSalary ( N INT ) RETURNS INT BEGIN +CREATE FUNCTION getNthHighestSalary ( N INT ) RETURNS INT READS SQL DATA BEGIN SET N = N - 1; RETURN ( diff --git a/notes/SQL 语法.md b/notes/SQL 语法.md index 113a0674..d2e7ac9a 100644 --- a/notes/SQL 语法.md +++ b/notes/SQL 语法.md @@ -42,7 +42,7 @@ 模式定义了数据如何存储、存储什么样的数据以及数据如何分解等信息,数据库和表都有模式。 -主键的值不允许修改,也不允许复用(不能将已经删除的主键值赋给新数据行的主键)。 +主键的值一般不修改,也不复用(不把已经删除的主键值赋给新数据行的主键),这是普遍遵循的习惯,数据库本身并不禁止。 SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。 @@ -403,7 +403,7 @@ HAVING num >= 2; ## 十四、子查询 -子查询中只能返回一个字段的数据。 +作为 IN 等条件与一个字段比较的子查询,只能返回一个字段的数据;MySQL 也支持 (col1, col2) IN (SELECT x, y ...) 这样同时比较多个字段。 可以将子查询的结果作为 WHERE 语句的过滤条件: @@ -581,9 +581,7 @@ WHERE col5 = val; 包含 in、out 和 inout 三种参数。 -给变量赋值都需要用 select into 语句。 - -每次只能给一个变量赋值,不支持集合的操作。 +可以用 SET 或者 SELECT ... INTO 给变量赋值。SELECT ... INTO 可以一次给多个变量赋值,但查询结果只能有一行,否则报错 1172(Result consisted of more than one row),多行结果要用下面的游标逐行处理。 ```sql delimiter // @@ -633,7 +631,10 @@ create procedure myprocedure(out ret int) repeat fetch mycursor into ret; - select ret; + # 最后一次 fetch 没有取到数据时 done 已经为 1,不能再输出 ret + if not done then + select ret; + end if; until done end repeat; close mycursor; @@ -658,7 +659,7 @@ SELECT @result; -- 获取结果 DELETE 触发器包含一个名为 OLD 的虚拟表,并且是只读的。 -UPDATE 触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表,其中 NEW 是可以被修改的,而 OLD 是只读的。 +UPDATE 触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表,其中 NEW 只能在 BEFORE 触发器中修改(SET NEW.col = ...),而 OLD 是只读的。 MySQL 的触发器可以使用 CALL 语句调用存储过程,但是该存储过程不能向客户端返回数据,也不能使用动态 SQL。 diff --git a/notes/微服务.md b/notes/微服务.md index 4755a320..49e6e30c 100644 --- a/notes/微服务.md +++ b/notes/微服务.md @@ -62,7 +62,7 @@ Spring Cloud 与 Spring Boot 的关系:Spring Boot 用来快速构建单个服 | --- | --- | --- | --- | | 服务的实例在哪里 | DiscoveryClient 接口 | Nacos | Eureka | | 选择哪个实例 | Spring Cloud LoadBalancer | Nacos 的权重负载均衡 | Ribbon | -| 怎么调用其它服务 | OpenFeign | — | — | +| 怎么调用其它服务 | OpenFeign | — | Feign | | 配置的集中管理和动态修改 | Spring Cloud Config | Nacos | Archaius | | 外部请求从哪里进入 | Spring Cloud Gateway | — | Zuul | | 下游故障时怎么保护自己 | Spring Cloud Circuit Breaker(Resilience4j) | Sentinel | Hystrix | diff --git a/notes/攻击技术.md b/notes/攻击技术.md index 4f3c27d6..598f9307 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -188,9 +188,9 @@ strSQL = "SELECT * FROM users;" Java 中的 PreparedStatement 是预先编译的 SQL 语句,可以传入适当参数并且多次执行。SQL 语句的结构在预编译时已经确定,传入的参数只会被当作数据,因此可以防止 SQL 注入的发生。 ```java -PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE userid=? AND password=?"); -stmt.setString(1, userid); -stmt.setString(2, password); +PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE name = ? AND pw = ?"); +stmt.setString(1, name); +stmt.setString(2, pw); ResultSet rs = stmt.executeQuery(); ``` @@ -204,7 +204,7 @@ Query SELECT * FROM users WHERE name = '1'' OR ''1''=''1' AND pw = '1'' OR '' #### 2. 单引号转换 -将传入的参数中的单引号转换为连续两个单引号。PHP 的 Magic Quotes 曾经自动完成这个功能,但是因为不可靠已经被移除,应该使用数据库驱动提供的转义函数,并且只在无法使用参数化查询时使用。 +将传入的参数中的单引号转换为连续两个单引号,或者在单引号前加反斜线(MySQL 默认两种都支持)。PHP 的 Magic Quotes 曾经自动给单引号等字符加反斜线,但是因为不可靠,已经在 PHP 5.4 中移除,应该使用数据库驱动提供的转义函数,并且只在无法使用参数化查询时使用。 #### 3. 最小权限 diff --git a/notes/计算机操作系统 - 链接.md b/notes/计算机操作系统 - 链接.md index ff9d3ba9..ef744736 100644 --- a/notes/计算机操作系统 - 链接.md +++ b/notes/计算机操作系统 - 链接.md @@ -52,7 +52,7 @@ gcc -o hello hello.c - 可执行目标文件:可以直接在内存中执行; - 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件; -- 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接; +- 共享目标文件:这是一种特殊的可重定位目标文件,可以在加载或者运行时被动态加载进内存并链接; ## 动态链接 diff --git a/notes/计算机网络 - 概述.md b/notes/计算机网络 - 概述.md index 9814aaaf..9cd94123 100644 --- a/notes/计算机网络 - 概述.md +++ b/notes/计算机网络 - 概述.md @@ -52,7 +52,7 @@ ### 2. 分组交换 -每个分组都有首部和尾部,包含了源地址和目的地址等控制信息,在同一个传输线路上同时传输多个分组互相不会影响,因此在同一条传输线路上允许同时传输多个分组,也就是说分组交换不需要占用传输线路。 +每个分组都有首部,包含了源地址和目的地址等控制信息,在同一个传输线路上同时传输多个分组互相不会影响,因此在同一条传输线路上允许同时传输多个分组,也就是说分组交换不需要独占传输线路。 在一个邮局通信系统中,邮局收到一份邮件之后,先存储下来,然后把相同目的地的邮件一起转发到下一个目的地,这个过程就是存储转发过程,分组交换也使用了存储转发过程。 @@ -123,7 +123,7 @@ TCP/IP 体系结构不严格遵循 OSI 分层概念,应用层可能会直接 在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。 -路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要传输层和应用层。 +路由器转发分组时只用到下面三层协议,因为路由器位于网络核心中,转发时不需要为进程或者应用程序提供服务,因此也就不需要传输层和应用层;路由器运行的路由协议另当别论,例如 BGP 使用 TCP 传输。 ## 参考资料 diff --git a/notes/计算机网络 - 物理层.md b/notes/计算机网络 - 物理层.md index 32dee01f..0b544e84 100644 --- a/notes/计算机网络 - 物理层.md +++ b/notes/计算机网络 - 物理层.md @@ -23,7 +23,7 @@

-实际的系统中还会把振幅和相位组合起来使用,例如正交振幅调制(Quadrature Amplitude Modulation, QAM)用 16 种不同的振幅和相位组合表示 4 个比特,一个码元就能传输更多的数据。 +实际的系统中还会把振幅和相位组合起来使用,例如正交振幅调制(Quadrature Amplitude Modulation, QAM)中的 16-QAM 用 16 种不同的振幅和相位组合表示 4 个比特,一个码元就能传输更多的数据。 ## 参考资料 diff --git a/notes/计算机网络 - 链路层.md b/notes/计算机网络 - 链路层.md index 7b8353a7..5174ac46 100644 --- a/notes/计算机网络 - 链路层.md +++ b/notes/计算机网络 - 链路层.md @@ -136,7 +136,8 @@ CSMA/CD 表示载波监听多点接入 / 碰撞检测。 PPP 的帧格式: - F 字段为帧的定界符; -- A 和 C 字段暂时没有意义; +- A 和 C 字段的值是固定的,分别为 0xFF 和 0x03,不携带信息; +- 协议字段指明信息部分是哪种协议的数据,例如 0x0021 表示 IP 数据报; - FCS 字段是使用 CRC 的检验序列; - 信息部分的长度不超过 1500 字节。 @@ -192,7 +193,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-使用 VLAN 干线连接来建立虚拟局域网,每台交换机上的一个特殊接口被设置为干线接口,以互连 VLAN 交换机。IEEE 定义了一种扩展的以太网帧格式 802.1Q,它在标准以太网帧上加进了 4 字节首部 VLAN 标签,用于表示该帧属于哪一个虚拟局域网。 +使用 VLAN 干线连接来建立虚拟局域网,每台交换机上的一个特殊接口被设置为干线接口,以互连 VLAN 交换机。IEEE 定义了一种扩展的以太网帧格式 802.1Q,它在标准以太网帧的源地址和类型字段之间插入了 4 字节的 VLAN 标签,用于表示该帧属于哪一个虚拟局域网。

diff --git a/notes/设计模式 - 单例.md b/notes/设计模式 - 单例.md index b0f62035..0b449479 100644 --- a/notes/设计模式 - 单例.md +++ b/notes/设计模式 - 单例.md @@ -11,7 +11,7 @@

### 实现 -#### Ⅰ 懒汉式-线程不安全 +#### 1. 懒汉式-线程不安全 以下实现中,私有静态变量 uniqueInstance 被延迟实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 @@ -34,7 +34,7 @@ public class Singleton { } ``` -#### Ⅱ 饿汉式-线程安全 +#### 2. 饿汉式-线程安全 线程不安全问题主要是由于 uniqueInstance 被实例化多次,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。 @@ -44,7 +44,7 @@ public class Singleton { private static Singleton uniqueInstance = new Singleton(); ``` -#### Ⅲ 懒汉式-线程安全 +#### 3. 懒汉式-线程安全 只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了实例化多次 uniqueInstance。 @@ -59,7 +59,7 @@ public static synchronized Singleton getUniqueInstance() { } ``` -#### Ⅳ 双重校验锁-线程安全 +#### 4. 双重校验锁-线程安全 uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。 @@ -98,15 +98,15 @@ if (uniqueInstance == null) { uniqueInstance 采用 volatile 关键字修饰也是很有必要的, `uniqueInstance = new Singleton();` 这段代码其实是分为三步执行: -1. 为 uniqueInstance 分配内存空间 -2. 初始化 uniqueInstance +1. 为对象分配内存空间 +2. 初始化对象 3. 将 uniqueInstance 指向分配的内存地址 但是由于 JVM 具有重排序的特性,执行顺序有可能变成 1>3>2。重排序在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。 使用 volatile 可以禁止 JVM 的重排序,保证在多线程环境下也能正常运行。 -#### Ⅴ 静态内部类实现 +#### 5. 静态内部类实现 当 Singleton 类被加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 `getUniqueInstance()` 方法从而触发 `SingletonHolder.INSTANCE` 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。 @@ -128,9 +128,11 @@ public class Singleton { } ``` -#### Ⅵ 枚举实现 +#### 6. 枚举实现 ```java +import java.lang.reflect.Constructor; + public enum Singleton { INSTANCE; @@ -159,14 +161,13 @@ public enum Singleton { System.out.println(firstSingleton.getObjName()); System.out.println(secondSingleton.getObjName()); - // 反射获取实例测试 + // 通过反射调用构造函数创建新的实例会失败 try { - Singleton[] enumConstants = Singleton.class.getEnumConstants(); - for (Singleton enumConstant : enumConstants) { - System.out.println(enumConstant.getObjName()); - } + Constructor constructor = Singleton.class.getDeclaredConstructor(String.class, int.class); + constructor.setAccessible(true); + constructor.newInstance("INSTANCE2", 1); } catch (Exception e) { - e.printStackTrace(); + System.out.println(e); } } } @@ -176,7 +177,7 @@ public enum Singleton { firstName secondName secondName -secondName +java.lang.IllegalArgumentException: Cannot reflectively create enum objects ``` 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止多次实例化的代码。该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 @@ -192,7 +193,7 @@ secondName ### JDK 中的应用 - [java.lang.Runtime#getRuntime()](http://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#getRuntime%28%29) - [java.awt.Desktop#getDesktop()](http://docs.oracle.com/javase/8/docs/api/java/awt/Desktop.html#getDesktop--) -- [java.lang.System#getSecurityManager()](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--) +- [java.lang.System#getSecurityManager()](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getSecurityManager--)(JDK 17 起已废弃,JEP 411) ## 参考资料 diff --git a/notes/设计模式 - 享元.md b/notes/设计模式 - 享元.md index bf29e556..4ac31fba 100644 --- a/notes/设计模式 - 享元.md +++ b/notes/设计模式 - 享元.md @@ -73,7 +73,7 @@ ExtrinsicState: y ``` ### JDK 中的应用 -Java 利用缓存来加速大量小对象的访问时间。 +Java 利用缓存复用大量的小对象,减少对象的创建和内存占用。 - java.lang.Integer#valueOf(int) - java.lang.Boolean#valueOf(boolean) diff --git a/notes/设计模式 - 代理.md b/notes/设计模式 - 代理.md index bfecfed8..896e3de6 100644 --- a/notes/设计模式 - 代理.md +++ b/notes/设计模式 - 代理.md @@ -87,7 +87,7 @@ public class ImageViewer { public static void main(String[] args) throws Exception { String image = "http://image.jpg"; - URL url = new URL(image); + URL url = URI.create(image).toURL(); HighResolutionImage highResolutionImage = new HighResolutionImage(url); ImageProxy imageProxy = new ImageProxy(highResolutionImage); imageProxy.showImage(); diff --git a/notes/设计模式 - 命令.md b/notes/设计模式 - 命令.md index 4fe0fdef..67226b13 100644 --- a/notes/设计模式 - 命令.md +++ b/notes/设计模式 - 命令.md @@ -119,7 +119,7 @@ public class Client { ### JDK 中的应用 - [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html) -- [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki) +- [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)(开源库,不属于 JDK) - [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html) ## 参考资料 diff --git a/notes/设计模式 - 备忘录.md b/notes/设计模式 - 备忘录.md index 790e919b..0c27b4ce 100644 --- a/notes/设计模式 - 备忘录.md +++ b/notes/设计模式 - 备忘录.md @@ -1,7 +1,7 @@ ## 备忘录(Memento) ### 意图 -在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。 +在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到之前保存的状态。 ### 类图 - Originator:原始对象 diff --git a/notes/设计模式 - 工厂方法.md b/notes/设计模式 - 工厂方法.md index fd2641c2..59a0bfe7 100644 --- a/notes/设计模式 - 工厂方法.md +++ b/notes/设计模式 - 工厂方法.md @@ -52,7 +52,6 @@ public class ConcreteFactory2 extends Factory { - [java.nio.charset.Charset](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-) - [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-) - [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-) -- [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--) ## 参考资料 diff --git a/notes/设计模式 - 模板方法.md b/notes/设计模式 - 模板方法.md index b1c8e3b9..80dad995 100644 --- a/notes/设计模式 - 模板方法.md +++ b/notes/设计模式 - 模板方法.md @@ -92,7 +92,7 @@ Tea.addCondiments ### JDK 中的应用 - java.util.Collections#sort() - java.io.InputStream#skip() -- java.io.InputStream#read() +- java.io.InputStream#read(byte[], int, int) - java.util.AbstractList#indexOf() ## 参考资料 diff --git a/notes/设计模式 - 生成器.md b/notes/设计模式 - 生成器.md index 1735782a..e65d153f 100644 --- a/notes/设计模式 - 生成器.md +++ b/notes/设计模式 - 生成器.md @@ -10,6 +10,8 @@ 以下是一个简易的 StringBuilder 实现,参考了 JDK 1.8 源码。 ```java +import java.util.Arrays; + public class AbstractStringBuilder { protected char[] value; diff --git a/notes/设计模式 - 组合.md b/notes/设计模式 - 组合.md index 71975fb9..31fd5141 100644 --- a/notes/设计模式 - 组合.md +++ b/notes/设计模式 - 组合.md @@ -80,7 +80,7 @@ public class Leaf extends Component { @Override public void add(Component component) { - throw new UnsupportedOperationException(); // 牺牲透明性换取单一职责原则,这样就不用考虑是叶子节点还是组合节点 + throw new UnsupportedOperationException(); // 牺牲单一职责原则换取透明性,这样就不用考虑是叶子节点还是组合节点 } @Override diff --git a/notes/设计模式 - 观察者.md b/notes/设计模式 - 观察者.md index b5453bf0..7b280998 100644 --- a/notes/设计模式 - 观察者.md +++ b/notes/设计模式 - 观察者.md @@ -124,10 +124,10 @@ StatisticsDisplay.update: 1.0 1.0 1.0 ``` ### JDK 中的应用 -- [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html) +- [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html)(JDK 9 起已废弃) - [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html) -- [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html) -- [RxJava](https://github.com/ReactiveX/RxJava) +- [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html)(Servlet API,不属于 JDK) +- [RxJava](https://github.com/ReactiveX/RxJava)(开源库,不属于 JDK) ## 参考资料 diff --git a/notes/设计模式 - 解释器.md b/notes/设计模式 - 解释器.md index dda454a3..6c1f9364 100644 --- a/notes/设计模式 - 解释器.md +++ b/notes/设计模式 - 解释器.md @@ -12,7 +12,7 @@ ### 实现 以下是一个规则检验器实现,具有 and 和 or 规则,通过规则可以构建一棵解析树,用来检验一个文本是否满足解析树定义的规则。 -例如一棵解析树为 D And (A Or (B C)),文本 "D A" 满足该解析树定义的规则。 +例如一棵解析树为 D And (A Or (B Or C)),文本 "D A" 满足该解析树定义的规则。 这里的 Context 指的是 String。 @@ -89,11 +89,11 @@ public class Client { Expression terminal2 = new TerminalExpression("B"); Expression terminal3 = new TerminalExpression("C"); Expression terminal4 = new TerminalExpression("D"); - // B C + // B Or C Expression alternation1 = new OrExpression(terminal2, terminal3); - // A Or (B C) + // A Or (B Or C) Expression alternation2 = new OrExpression(terminal1, alternation1); - // D And (A Or (B C)) + // D And (A Or (B Or C)) return new AndExpression(terminal4, alternation2); } @@ -116,7 +116,7 @@ false - [java.util.Pattern](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) - [java.text.Normalizer](http://docs.oracle.com/javase/8/docs/api/java/text/Normalizer.html) - All subclasses of [java.text.Format](http://docs.oracle.com/javase/8/docs/api/java/text/Format.html) -- [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html) +- [javax.el.ELResolver](http://docs.oracle.com/javaee/7/api/javax/el/ELResolver.html)(EL API,不属于 JDK) ## 参考资料 diff --git a/notes/设计模式 - 责任链.md b/notes/设计模式 - 责任链.md index 2f98ad66..db61bca3 100644 --- a/notes/设计模式 - 责任链.md +++ b/notes/设计模式 - 责任链.md @@ -121,8 +121,8 @@ request2 is handle by ConcreteHandler2 ### JDK 中的应用 - [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29) -- [Apache Commons Chain](https://commons.apache.org/dormant/commons-chain/) -- [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-) +- [Apache Commons Chain](https://commons.apache.org/dormant/commons-chain/)(开源库,不属于 JDK) +- [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)(Servlet API,不属于 JDK) ## 参考资料 diff --git a/notes/设计模式 - 迭代器.md b/notes/设计模式 - 迭代器.md index 13b2fdf3..1d1ecbc4 100644 --- a/notes/设计模式 - 迭代器.md +++ b/notes/设计模式 - 迭代器.md @@ -6,7 +6,7 @@ ### 类图 - Aggregate 是聚合类,其中 createIterator() 方法可以产生一个 Iterator; - Iterator 主要定义了 hasNext() 和 next() 方法; -- Client 组合了 Aggregate,为了迭代遍历 Aggregate,也需要组合 Iterator。 +- Client 依赖 Aggregate,为了迭代遍历 Aggregate,也需要依赖 Iterator。

diff --git a/notes/设计模式 - 适配器.md b/notes/设计模式 - 适配器.md index 98bd3877..9ab96a86 100644 --- a/notes/设计模式 - 适配器.md +++ b/notes/设计模式 - 适配器.md @@ -63,7 +63,6 @@ public class Client { - [java.util.Arrays#asList()](http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList%28T...%29) - [java.util.Collections#list()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#list-java.util.Enumeration-) - [java.util.Collections#enumeration()](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#enumeration-java.util.Collection-) -- [javax.xml.bind.annotation.adapters.XMLAdapter](http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html#marshal-BoundType-) ## 参考资料 diff --git a/notes/集群.md b/notes/集群.md index 8a6bebe8..cda657f6 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -149,7 +149,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 #### 4. 网络层 -在操作系统内核进程获取网络数据包,根据负载均衡算法计算源服务器的 IP 地址,并修改请求数据包的目的 IP 地址,最后进行转发。 +在操作系统内核中获取网络数据包,根据负载均衡算法计算源服务器的 IP 地址,并修改请求数据包的目的 IP 地址,最后进行转发。 源服务器返回的响应也需要经过负载均衡服务器,通常是让负载均衡服务器同时作为集群的网关服务器来实现。对应 LVS 的 NAT 模式。 @@ -169,7 +169,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 这是一种三角传输模式,被称为直接路由,对应 LVS 的 DR 模式,要求源服务器和负载均衡服务器位于同一个局域网内。对于提供下载和视频服务的网站来说,直接路由避免了大量的网络传输数据经过负载均衡服务器。 -网络层和链路层的方式不解析应用层协议,属于四层负载均衡。链路层是目前大型网站使用最广的负载均衡转发方式,在 Linux 平台可以使用的负载均衡服务器为 LVS(Linux Virtual Server),通常用 LVS 做四层负载均衡,再用 Nginx 做七层负载均衡。 +网络层和链路层的方式不解析应用层协议,属于四层负载均衡。链路层负载均衡的响应不经过负载均衡服务器,性能很好,在 Linux 平台可以使用的负载均衡服务器为 LVS(Linux Virtual Server),通常用 LVS 做四层负载均衡,再用 Nginx 做七层负载均衡。 参考: diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 9494ea87..dfc0942c 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -246,11 +246,11 @@ School "1" - "*" Student ### 依赖关系 (Dependency) -和关联关系不同的是,依赖关系是在运行过程中起作用的。A 类和 B 类是依赖关系主要有三种形式: +和关联关系不同的是,依赖关系是在运行过程中起作用的。A 类依赖 B 类主要有三种形式: -- A 类是 B 类方法的局部变量; -- A 类是 B 类方法的参数; -- A 类向 B 类发送消息,从而影响 B 类发生变化。 +- B 类是 A 类方法中的局部变量; +- B 类是 A 类方法的参数; +- A 类向 B 类发送消息(调用 B 类的方法),从而影响 B 类发生变化。