diff --git a/README.md b/README.md index 54b0010f..14bb6fdb 100755 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle - [Java 18 新特性概览](./docs/java/new-features/java18.md) - [Java 19 新特性概览](./docs/java/new-features/java19.md) - [Java 20 新特性概览](./docs/java/new-features/java20.md) +- [Java 21 新特性概览](./docs/java/new-features/java21.md) ## 计算机基础 diff --git a/docs/.vuepress/sidebar/index.ts b/docs/.vuepress/sidebar/index.ts index 462233f4..7ffbbf2c 100644 --- a/docs/.vuepress/sidebar/index.ts +++ b/docs/.vuepress/sidebar/index.ts @@ -166,6 +166,7 @@ export default sidebar({ "java18", "java19", "java20", + "java21", ], }, ], diff --git a/docs/cs-basics/operating-system/shell-intro.md b/docs/cs-basics/operating-system/shell-intro.md index 38e3d824..1c45e431 100644 --- a/docs/cs-basics/operating-system/shell-intro.md +++ b/docs/cs-basics/operating-system/shell-intro.md @@ -348,7 +348,7 @@ a 不等于 b 使用方式很简单,比如我们定义好了一个文件路径`file="/usr/learnshell/test.sh"` 如果我们想判断这个文件是否可读,可以这样`if [ -r $file ]` 如果想判断这个文件是否可写,可以这样`-w $file`,是不是很简单。 -## shell 流程控制 +## Shell 流程控制 ### if 条件语句 @@ -454,7 +454,7 @@ do done ``` -## shell 函数 +## Shell 函数 ### 不带参数没有返回值的函数 diff --git a/docs/home.md b/docs/home.md index e17bd816..4f321072 100644 --- a/docs/home.md +++ b/docs/home.md @@ -121,6 +121,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8](https://docs.oracle. - [Java 18 新特性概览](./java/new-features/java18.md) - [Java 19 新特性概览](./java/new-features/java19.md) - [Java 20 新特性概览](./java/new-features/java20.md) +- [Java 21 新特性概览](./java/new-features/java21.md) ## 计算机基础 diff --git a/docs/java/new-features/java19.md b/docs/java/new-features/java19.md index 3e9a931e..6fe62eb7 100644 --- a/docs/java/new-features/java19.md +++ b/docs/java/new-features/java19.md @@ -82,6 +82,7 @@ assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"}); Java 虚拟线程的详细解读和原理可以看下面这两篇文章: +- [虚拟线程原理及性能分析|得物技术](https://mp.weixin.qq.com/s/vdLXhZdWyxc6K-D3Aj03LA) - [Java19 正式 GA!看虚拟线程如何大幅提高系统吞吐量](https://mp.weixin.qq.com/s/yyApBXxpXxVwttr01Hld6Q) - [虚拟线程 - VirtualThread 源码透视](https://www.cnblogs.com/throwable/p/16758997.html) diff --git a/docs/java/new-features/java21.md b/docs/java/new-features/java21.md index fa6c371d..0eccb546 100644 --- a/docs/java/new-features/java21.md +++ b/docs/java/new-features/java21.md @@ -9,7 +9,7 @@ JDK 21 于 2023 年 9 月 19 日 发布,这是一个非常重要的版本, JDK21 是 LTS(长期支持版),至此为止,目前有 JDK8、JDK11、JDK17 和 JDK21 这四个长期支持版了。 -JDK 21 共有 15 个新特性: +JDK 21 共有 15 个新特性,这篇文章会挑选其中较为重要的一些新特性进行详细介绍: - [JEP 430:String Templates(字符串模板)](https://openjdk.org/jeps/430)(预览) - [JEP 431:Sequenced Collections(序列化集合)](https://openjdk.org/jeps/431) @@ -18,8 +18,16 @@ JDK 21 共有 15 个新特性: - [JEP 440:Record Patterns(记录模式)](https://openjdk.org/jeps/440) +- [JEP 441:Pattern Matching for switch(switch 的模式匹配)](https://openjdk.org/jeps/442) + +- [JEP 442:Foreign Function & Memory API(外部函数和内存 API)](https://openjdk.org/jeps/442)(第三次预览) + +- [JEP 443:Unnamed Patterns and Variables(未命名模式和变量](https://openjdk.org/jeps/443)(预览) + - [JEP 444:Virtual Threads(虚拟线程)](https://openjdk.org/jeps/444) +- [JEP 445:Unnamed Classes and Instance Main Methods(未命名类和实例 main 方法 )](https://openjdk.org/jeps/445)(预览) + ## JEP 430:字符串模板(预览) String Templates(字符串模板) 目前仍然是 JDK 21 中的一个预览功能。 @@ -119,7 +127,134 @@ String time = STR."The current time is \{ ## JEP431:序列化集合 -JDK 21 引入了一种新的集合类型:**Sequenced Collections(序列化集合)**。 +JDK 21 引入了一种新的集合类型:**Sequenced Collections(序列化集合,也叫有序集合)**,这是一种具有确定出现顺序(encounter order)的集合(无论我们遍历这样的集合多少次,元素的出现顺序始终是固定的)。序列化集合提供了处理集合的第一个和最后一个元素以及反向视图(与原始集合相反的顺序)的简单方法。 + +Sequenced Collections 包括以下三个接口: + +- [`SequencedCollection`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedCollection.html) +- [`SequencedSet`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedSet.html) +- [`SequencedMap`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedMap.html) + +`SequencedCollection` 接口继承了 `Collection`接口, 提供了在集合两端访问、添加或删除元素以及获取集合的反向视图的方法。 + +```java +interface SequencedCollection extends Collection { + + // New Method + + SequencedCollection reversed(); + + // Promoted methods from Deque + + void addFirst(E); + void addLast(E); + + E getFirst(); + E getLast(); + + E removeFirst(); + E removeLast(); +} +``` + +`List` 和 `Deque` 接口实现了`SequencedCollection` 接口。 + +这里以 `ArrayList` 为例,演示一下实际使用效果: + +```java +ArrayList arrayList = new ArrayList<>(); + +arrayList.add(1); // List contains: [1] + +arrayList.addFirst(0); // List contains: [0, 1] +arrayList.addLast(2); // List contains: [0, 1, 2] + +Integer firstElement = arrayList.getFirst(); // 0 +Integer lastElement = arrayList.getLast(); // 2 + +List reversed = arrayList.reversed(); +System.out.println(reversed); // Prints [2, 1, 0] +``` + +`SequencedSet`接口直接继承了 `SequencedCollection` 接口并重写了 `reversed()` 方法。 + +```java +interface SequencedSet extends SequencedCollection, Set { + + SequencedSet reversed(); +} +``` + +`SortedSet` 和 `LinkedHashSet` 实现了`SequencedSet`接口。 + +这里以 `LinkedHashSet` 为例,演示一下实际使用效果: + +```java +LinkedHashSet linkedHashSet = new LinkedHashSet<>(List.of(1, 2, 3)); + +Integer firstElement = linkedHashSet.getFirst(); // 1 +Integer lastElement = linkedHashSet.getLast(); // 3 + +linkedHashSet.addFirst(0); //List contains: [0, 1, 2, 3] +linkedHashSet.addLast(4); //List contains: [0, 1, 2, 3, 4] + +System.out.println(linkedHashSet.reversed()); //Prints [5, 3, 2, 1, 0] +``` + +`SequencedMap` 接口继承了 `Map`接口, 提供了在集合两端访问、添加或删除键值对、获取包含 key 的 `SequencedSet`、包含 value 的 `SequencedCollection`、包含 entry(键值对) 的 `SequencedSet`以及获取集合的反向视图的方法。 + +```java +interface SequencedMap extends Map { + + // New Methods + + SequencedMap reversed(); + + SequencedSet sequencedKeySet(); + SequencedCollection sequencedValues(); + SequencedSet> sequencedEntrySet(); + + V putFirst(K, V); + V putLast(K, V); + + + // Promoted Methods from NavigableMap + + Entry firstEntry(); + Entry lastEntry(); + + Entry pollFirstEntry(); + Entry pollLastEntry(); +} +``` + +`SortedMap` 和`LinkedHashMap` 实现了`SequencedMap` 接口。 + +这里以 `LinkedHashMap` 为例,演示一下实际使用效果: + +```java +LinkedHashMap map = new LinkedHashMap<>(); + +map.put(1, "One"); +map.put(2, "Two"); +map.put(3, "Three"); + +map.firstEntry(); //1=One +map.lastEntry(); //3=Three + +System.out.println(map); //{1=One, 2=Two, 3=Three} + +Map.Entry first = map.pollFirstEntry(); //1=One +Map.Entry last = map.pollLastEntry(); //3=Three + +System.out.println(map); //{2=Two} + +map.putFirst(1, "One"); //{1=One, 2=Two} +map.putLast(3, "Three"); //{1=One, 2=Two, 3=Three} + +System.out.println(map); //{1=One, 2=Two, 3=Three} +System.out.println(map.reversed()); //{3=Three, 2=Two, 1=One} +``` ## JEP 439:分代 ZGC @@ -144,6 +279,63 @@ java -XX:+UseZGC -XX:+ZGenerational ... [Java 20 新特性概览](./java20.md)已经详细介绍过记录模式,这里就不重复了。 +## JEP 441:switch 的模式匹配 + +增强 Java 中的 switch 表达式和语句,允许在 case 标签中使用模式。当模式匹配时,执行 case 标签对应的代码。 + +在下面的代码中,switch 表达式使用了类型模式来进行匹配。 + +```java +static String formatterPatternSwitch(Object obj) { + return switch (obj) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> obj.toString(); + }; +} +``` + +## JEP 442: 外部函数和内存 API(第三次预览) + +Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。 + +外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 [JEP 412](https://openjdk.java.net/jeps/412) 提出。Java 18 中进行了第二次孵化,由[JEP 419](https://openjdk.org/jeps/419) 提出。Java 19 中是第一次预览,由 [JEP 424](https://openjdk.org/jeps/424) 提出。JDK 20 中是第二次预览,由 [JEP 434](https://openjdk.org/jeps/434) 提出。JDK 21 中是第三次预览,由 [JEP 442](https://openjdk.org/jeps/442) 提出。 + +在 [Java 19 新特性概览](./java19.md) 中,我有详细介绍到外部函数和内存 API,这里就不再做额外的介绍了。 + +## JEP 443:未命名模式和变量(预览) + +未命名模式和变量使得我们可以使用下划线 `_` 表示未命名的变量以及模式匹配时不使用的组件,旨在提高代码的可读性和可维护性。 + +未命名变量的典型场景是 `try-with-resources` 语句、 `catch` 子句中的异常变量和`for`循环。当变量不需要使用的时候就可以使用下划线 `_`代替,这样清晰标识未被使用的变量。 + +```java +try (var _ = ScopedContext.acquire()) { + // No use of acquired resource +} +try { ... } +catch (Exception _) { ... } +catch (Throwable _) { ... } + +for (int i = 0, _ = runOnce(); i < arr.length; i++) { + ... +} +``` + +未命名模式是一个无条件的模式,并不绑定任何值。未命名模式变量出现在类型模式中。 + +```java +if (r instanceof ColoredPoint(_, Color c)) { ... c ... } + +switch (b) { + case Box(RedBall _), Box(BlueBall _) -> processBox(b); + case Box(GreenBall _) -> stopProcessing(); + case Box(_) -> pickAnotherBox(); +} +``` + ## JEP 444:虚拟线程 虚拟线程是一项重量级的更新,一定一定要重视! @@ -152,6 +344,39 @@ java -XX:+UseZGC -XX:+ZGenerational ... [Java 20 新特性概览](./java20.md)已经详细介绍过虚拟线程,这里就不重复了。 +## JEP 445:未命名类和实例 main 方法 (预览) + +这个特性主要简化了 `main` 方法的的声明。对于 Java 初学者来说,这个 `main` 方法的声明引入了太多的 Java 语法概念,不利于初学者快速上手。 + +没有使用该特性之前定义一个 `main` 方法: + +```java +public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} +``` + +使用该新特性之后定义一个 `main` 方法: + +```java +class HelloWorld { + void main() { + System.out.println("Hello, World!"); + } +} +``` + +进一步精简(未命名的类允许我们不定义类名): + +```java +void main() { + System.out.println("Hello, World!"); +} +``` + ## 参考 - Java 21 String Templates: +- Java 21 Sequenced Collections:https://howtodoinjava.com/java/sequenced-collections/ diff --git a/docs/system-design/J2EE基础知识.md b/docs/system-design/J2EE基础知识.md index ebef61dd..b1b8264a 100644 --- a/docs/system-design/J2EE基础知识.md +++ b/docs/system-design/J2EE基础知识.md @@ -1,3 +1,5 @@ + + ## Servlet 总结 在 Java Web 程序中,**Servlet**主要负责接收用户请求 `HttpServletRequest`,在`doGet()`,`doPost()`中做相应的处理,并将回应`HttpServletResponse`反馈给用户。**Servlet** 可以设置初始化参数,供 Servlet 内部使用。一个 Servlet 类只会有一个实例,在它初始化时调用`init()`方法,销毁时调用`destroy()`方法**。**Servlet 需要在 web.xml 中配置(MyEclipse 中创建 Servlet 会自动配置),**一个 Servlet 可以设置多个 URL 访问**。**Servlet 不是线程安全**,因此要谨慎使用类变量。