<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>后端 on 小盒子的技术分享</title><link>https://xiaobox.github.io/categories/%E5%90%8E%E7%AB%AF/</link><description>Recent content in 后端 on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 03 Mar 2026 04:38:15 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/categories/%E5%90%8E%E7%AB%AF/index.xml" rel="self" type="application/rss+xml"/><item><title>动画演示 Node.js 的事件循环</title><link>https://xiaobox.github.io/p/2026-03-03-dong-hua-yan-shi-node-js-de-shi-jian-xun-huan/</link><pubDate>Tue, 03 Mar 2026 04:38:15 +0000</pubDate><guid>https://xiaobox.github.io/p/2026-03-03-dong-hua-yan-shi-node-js-de-shi-jian-xun-huan/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2026-03-03-dong-hua-yan-shi-node-js-de-shi-jian-xun-huan/cover.jpg" alt="Featured image of post 动画演示 Node.js 的事件循环" /&gt;&lt;p&gt;如果把 Node.js 比作一家快餐店：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;主线程（前台收银员）：&lt;/strong&gt; 只有一个人。他负责接待顾客点单（执行同步代码）。他动作很快，绝不离开柜台。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;异步任务（复杂的后厨订单）：&lt;/strong&gt; 顾客点了需要烤 20 分钟的披萨（读取大文件）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;libuv/底层系统（后厨团队/烤箱）：&lt;/strong&gt; 收银员把订单贴到后厨窗口就继续接待下一位顾客了。后厨团队（线程池）或者烤箱（系统内核）开始默默干活。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Callback Queue（出餐台）：&lt;/strong&gt; 披萨烤好了，后厨把它放到出餐台，并附上小票“3号桌的披萨好了”。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event Loop（收银员的习惯动作）：&lt;/strong&gt; 收银员每服务完一个顾客（主线程空闲），就会下意识地回头看一眼出餐台。如果看到有做好的餐，就把它端给顾客（执行回调函数）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>搞懂 ThreadLocal，其实就三件事：它是谁？它在哪？用完它咋办？</title><link>https://xiaobox.github.io/p/2025-08-21-gao-dong-threadlocal-qi-shi-jiu-san-jian-shi-ta-shi-shui-ta/</link><pubDate>Thu, 21 Aug 2025 10:52:24 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-08-21-gao-dong-threadlocal-qi-shi-jiu-san-jian-shi-ta-shi-shui-ta/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-08-21-gao-dong-threadlocal-qi-shi-jiu-san-jian-shi-ta-shi-shui-ta-/cover.jpg" alt="Featured image of post 搞懂 ThreadLocal，其实就三件事：它是谁？它在哪？用完它咋办？" /&gt;&lt;h1 id="缘起"&gt;&lt;a href="#%e7%bc%98%e8%b5%b7" class="header-anchor"&gt;&lt;/a&gt;缘起
&lt;/h1&gt;&lt;p&gt;这两天又用到了 &lt;code&gt;ThreadLocal&lt;/code&gt; ,时间一长，很多细节都想不起来了，现翻源码 😂&lt;/p&gt;
&lt;p&gt;想着干脆写个笔记记录一下，其实之前写过有关 &lt;code&gt;ThreadLocal&lt;/code&gt; 的文章，现在回过头看觉得一些细节写的交待的不好，那么就再写一遍吧。&lt;/p&gt;
&lt;p&gt;这一次的目标就是搞清楚 &lt;strong&gt;Threadlocal 它到底是怎么隔离线程数据的，好在哪？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当然也要挖一挖那个潜在的 &lt;strong&gt;内存泄漏风险&lt;/strong&gt;，看看它在 Java 不同版本里头有没有啥变化。&lt;/p&gt;
&lt;h1 id="threadlocal-它根本上是干嘛的"&gt;&lt;a href="#threadlocal-%e5%ae%83%e6%a0%b9%e6%9c%ac%e4%b8%8a%e6%98%af%e5%b9%b2%e5%98%9b%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;ThreadLocal 它根本上是干嘛的？
&lt;/h1&gt;&lt;p&gt;简单来说， ThreadLocal 就是给每个线程(注意是每个线程) 一个变量的独立副本。&lt;/p&gt;
&lt;p&gt;你可以想象一下，比如说用户 ID 或者一个事务 ID 这种需要跟某个线程绑定的数据，用它就特别合适。&lt;strong&gt;它解决的不是那种多线程怎么共享数据的问题，而是怎么管好单个线程自己用的数据。&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id="反向存储"&gt;&lt;a href="#%e5%8f%8d%e5%90%91%e5%ad%98%e5%82%a8" class="header-anchor"&gt;&lt;/a&gt;反向存储
&lt;/h1&gt;&lt;p&gt;它用了一个挺有意思的设计，有人叫它 “反向存储”&lt;/p&gt;
&lt;p&gt;我根据 ThreadLocal 的内部结构梳理了一个结构图，如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;$ terminal┌─────────────────────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;│ JVM 堆内存 - 全局共享区域 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;│ ┌─────────────────┐ ┌─────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;│ │ ThreadLocal1 │ │ ThreadLocal2 │ ← 全局唯一实例 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;│ │ &lt;span class="o"&gt;(&lt;/span&gt;COUNTER&lt;span class="o"&gt;)&lt;/span&gt; │ │ &lt;span class="o"&gt;(&lt;/span&gt;NAME&lt;span class="o"&gt;)&lt;/span&gt; │ 所有线程共享 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;│ └─────────────────┘ └─────────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;└─────────────────────────────────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; ↑ ↑
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; │ 作为key引用 │ 作为key引用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;┌─────────────────────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;│ 线程独立存储区域 │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;│ ┌─────────────────┐ ┌─────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;│ │ Thread-1 │ │ Thread-2 │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;│ │ threadLocals ──┼──┐ ┌──┼── threadLocals │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;│ └─────────────────┘ │ │ └─────────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;│ ┌────────────────────▼──┐ ┌──▼────────────────────┐ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;│ │ ThreadLocalMap-1 │ │ ThreadLocalMap-2 │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;│ │ Entry&lt;span class="o"&gt;[]&lt;/span&gt; table │ │ Entry&lt;span class="o"&gt;[]&lt;/span&gt; table │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;│ │ ┌─────────────────┐ │ │ ┌─────────────────┐ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ Entry&lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt; │ │ │ │ Entry&lt;span class="o"&gt;[&lt;/span&gt;0&lt;span class="o"&gt;]&lt;/span&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ key: COUNTER │ │ │ │ key: COUNTER │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ value: &lt;span class="m"&gt;100&lt;/span&gt; │ │ │ │ value: &lt;span class="m"&gt;200&lt;/span&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;│ │ └─────────────────┘ │ │ └─────────────────┘ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;│ │ ┌─────────────────┐ │ │ ┌─────────────────┐ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ Entry&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt; │ │ │ │ Entry&lt;span class="o"&gt;[&lt;/span&gt;1&lt;span class="o"&gt;]&lt;/span&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ key: NAME │ │ │ │ key: NAME │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;│ │ │ value:&lt;span class="s2"&gt;&amp;#34;Thread1&amp;#34;&lt;/span&gt; │ │ │ │ value:&lt;span class="s2"&gt;&amp;#34;Thread2&amp;#34;&lt;/span&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;│ │ └─────────────────┘ │ │ └─────────────────┘ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;│ └───────────────────────┘ └───────────────────────┘ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt;│ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt;└─────────────────────────────────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从图上可以看到，实际上是每个 &lt;code&gt;Thread&lt;/code&gt; 对象它自己内部持有一个map，这个 map 就是 &lt;code&gt;ThreadLocalMap&lt;/code&gt;，每个线程都有一个。&lt;/p&gt;
&lt;p&gt;我们从源码中也能看到：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;terminal&lt;/span&gt;&lt;span class="c1"&gt;// Thread 类的关键字段（简化版）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Runnable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 每个 Thread 实例都有自己独立的这个字段！&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ThreadLocalMap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threadLocals&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ThreadLocalMap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inheritableThreadLocals&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 其他字段...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后那个 ThreadLocal 变量本身就是我们代码里定义的那个，通常是个 static final 的全局变量。它其实是充当了所有这些不同的 &lt;code&gt;ThreadLocalMap&lt;/code&gt; 里面的 entry 的 key。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;$ terminal// ThreadLocalMap 的关键实现
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;static class ThreadLocalMap &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; // Entry 继承 WeakReference，key 是 ThreadLocal 对象的弱引用
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; static class Entry extends WeakReference&amp;lt;ThreadLocal&amp;lt;?&amp;gt;&amp;gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; Object value&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; Entry&lt;span class="o"&gt;(&lt;/span&gt;ThreadLocal&amp;lt;?&amp;gt; k, Object v&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; super&lt;span class="o"&gt;(&lt;/span&gt;k&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; // k 是全局共享的 ThreadLocal 对象
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; v&lt;span class="p"&gt;;&lt;/span&gt; // v 是线程独立的值
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; // 每个 ThreadLocalMap 都有自己独立的 Entry 数组
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; private Entry&lt;span class="o"&gt;[]&lt;/span&gt; table&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; // 构造函数：每个线程调用时都会创建新的实例
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; ThreadLocalMap&lt;span class="o"&gt;(&lt;/span&gt;ThreadLocal&amp;lt;?&amp;gt; firstKey, Object firstValue&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; new Entry&lt;span class="o"&gt;[&lt;/span&gt;INITIAL_CAPACITY&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; int &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; firstKey.threadLocalHashCode &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;INITIAL_CAPACITY - 1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; table&lt;span class="o"&gt;[&lt;/span&gt;i&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; new Entry&lt;span class="o"&gt;(&lt;/span&gt;firstKey, firstValue&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; setThreshold&lt;span class="o"&gt;(&lt;/span&gt;INITIAL_CAPACITY&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;就是说 &lt;code&gt;Threadlocal&lt;/code&gt; 这个钥匙是大家都能看到的，是共享的，但是存东西的柜子也就是 &lt;code&gt;ThreadLocalMap&lt;/code&gt; 是每个线程自己的，是互相隔离的。&lt;/p&gt;
&lt;h2 id="内部存储"&gt;&lt;a href="#%e5%86%85%e9%83%a8%e5%ad%98%e5%82%a8" class="header-anchor"&gt;&lt;/a&gt;内部存储
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;这个 ThreadLocalMap 它怎么通过 ThreadLocal 这个键找到对应的值呢？它里面是咋存的？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;实际上它是用 ThreadLocal 实例本身的哈希码，这个哈希码会经过一个计算，然后确定在 map 内部数组里的一个位置。这个计算方法还挺讲究的，用了一个特殊的数字，就是为了让这些键能均匀地散开。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;$ terminal// 构造函数：每个线程调用时都会创建新的实例
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;ThreadLocalMap&lt;span class="o"&gt;(&lt;/span&gt;ThreadLocal&amp;lt;?&amp;gt; firstKey, Object firstValue&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; new Entry&lt;span class="o"&gt;[&lt;/span&gt;INITIAL_CAPACITY&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; int &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; firstKey.threadLocalHashCode &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;INITIAL_CAPACITY - 1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; table&lt;span class="o"&gt;[&lt;/span&gt;i&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; new Entry&lt;span class="o"&gt;(&lt;/span&gt;firstKey, firstValue&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; setThreshold&lt;span class="o"&gt;(&lt;/span&gt;INITIAL_CAPACITY&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;ThreadLocal中有一个属性为HASH_INCREMENT = 0x61c88647。这个值很特殊，它是斐波那契数 也叫 黄金分割数。hash增量为 这个数字，带来的好处就是 hash 分布非常均匀。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;要是算出来的位置已经被占了，就是所谓的哈希冲突，它就用一种叫&lt;strong&gt;线性探测&lt;/strong&gt;的方法来解决，简单说就是如果这个位置有人了，他就看下一个位置空不空，再不行就再看下一个，一直找到空位为止。&lt;/p&gt;
&lt;p&gt;因为这个 map 是线程私有的，不存在多个线程同时来抢位置的问题，所以这种简单的方法就够用了，效率也还行。&lt;/p&gt;
&lt;h2 id="隔离机制"&gt;&lt;a href="#%e9%9a%94%e7%a6%bb%e6%9c%ba%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;隔离机制
&lt;/h2&gt;&lt;p&gt;这个 “反向存储” ，有点儿反直觉：不是 ThreadLocal 对象持有多个线程的值，而是 每个 Thread 对象持有自己的 ThreadLocalMap，ThreadLocalMap 以 ThreadLocal 对象为 key，存储该线程的值。&lt;/p&gt;
&lt;p&gt;我们再具体总结一下 ThreadLocal 的隔离机制，实际上它是一个 &amp;ldquo;部分共享，部分独立&amp;rdquo; 的机制。&lt;/p&gt;
&lt;p&gt;1.ThreadLocal 对象全局共享：static final 修饰，JVM 中只有一个实例，所有线程都引用同一个 ThreadLocal 对象&lt;/p&gt;
&lt;p&gt;2.ThreadLocalMap 线程独立：存储在 Thread.threadLocals 字段中，每个 Thread 实例都有自己的 threadLocals 字段，调用 createMap() 时，给不同线程创建不同的 ThreadLocalMap 实例&lt;/p&gt;
&lt;p&gt;3.Entry 数组线程独立：每个 ThreadLocalMap 都有自己的 Entry[] table，虽然 Entry 的 key 都指向同一个 ThreadLocal 对象，但 Entry 对象本身和 value 都是线程独立的&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“ThreadLocal 就是一把“通用钥匙”，它不存东西，而是帮每个线程打开自己的“专属保险箱”。”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;这就是 ThreadLocal 精妙设计的核心：通过线程对象的实例字段实现存储隔离，通过全局 ThreadLocal 对象实现访问统一。&lt;/p&gt;
&lt;h1 id="内存泄露风险"&gt;&lt;a href="#%e5%86%85%e5%ad%98%e6%b3%84%e9%9c%b2%e9%a3%8e%e9%99%a9" class="header-anchor"&gt;&lt;/a&gt;内存泄露风险
&lt;/h1&gt;&lt;p&gt;这个风险主要来自于 &lt;code&gt;ThreadLocalMap&lt;/code&gt; 存数据的方式。特别是它的键，这个 map 里面的键也就是咱们那个 &lt;code&gt;ThreadLocal&lt;/code&gt; 对象实例，它不是直接存的，它是被一个叫做 &lt;code&gt;weak reference&lt;/code&gt;，也就是弱引用的东西包了一层&lt;/p&gt;
&lt;h2 id="弱引用"&gt;&lt;a href="#%e5%bc%b1%e5%bc%95%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;弱引用
&lt;/h2&gt;&lt;p&gt;这个弱引用跟我们平时用的那种普通的引用就是强引用有啥不一样？&lt;/p&gt;
&lt;p&gt;咱们平时用的强引用，只要这个引用还在，垃圾回收器（GC） 就不会把那个对象收走，但弱引用不一样， GC 在扫描的时候如果发现一个对象只被弱引用指着，没有强引用指向它了，那 GC 就可以把它回收掉。所以在 &lt;code&gt;ThreadLocalMap&lt;/code&gt; 这里，如果你代码里别的地方不再持有那个 &lt;code&gt;Threadlocal&lt;/code&gt; 实例的强引用了,比如说那个类被卸载了，或者实例变量不再被访问了,类似这种情况，那 GC 就可能把这个 Threadlocal 对象本身回收掉，这时候 map 里面那个 entry 的键就变成了null。&lt;/p&gt;
&lt;h3 id="键没了变成-null-了那不是正好吗"&gt;&lt;a href="#%e9%94%ae%e6%b2%a1%e4%ba%86%e5%8f%98%e6%88%90-null-%e4%ba%86%e9%82%a3%e4%b8%8d%e6%98%af%e6%ad%a3%e5%a5%bd%e5%90%97" class="header-anchor"&gt;&lt;/a&gt;键没了，变成 null 了，那不是正好吗？
&lt;/h3&gt;&lt;p&gt;键没了，变成 null 了，说明这个条目没用了，可以清掉了。那不是正好吗？&lt;/p&gt;
&lt;p&gt;坑就在这，虽然键是弱引用， GC 可能回收它，但是和这个键关联的那个值（value），它是被强引用持有的。持有它就是 Threadlocalmap 里面的那个 entry 对象，这个 entry 对象本身强引用着那个 value。&lt;/p&gt;
&lt;p&gt;我们来捋一下：&lt;strong&gt;Threadlocal 键被弱引用包装，可能被 GC 回收变 null，但存的那个 value 被 entry 对象强引用。 然后这个 entry 对象又被 ThreadLocalMap 持有，ThreadLocalMap 又被那个 Thread 对象持有。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;整个引用链条如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="图片" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-08-21-gao-dong-threadlocal-qi-shi-jiu-san-jian-shi-ta-shi-shui-ta-/001-9dc9dd97.png"&gt;&lt;/p&gt;
&lt;p&gt;只要这个线程还活着，比如线程池里的线程（它可能活很久，线程池里的线程会复用），然后如果这个线程后续一直没有再调用这个 Threadlocal 的 set、get 或者 remove 方法，这些方法在执行的时候会顺便检查一下清理掉那些键为 null 的entry，但如果一直没调用，那这个键虽然是 null 了，但那个 value 因为被 entry 强引用着，就一直没法被 GC 回收。&lt;strong&gt;这就泄露了。那个 value 对象就一直占着内存，明明逻辑上可能已经没用了。这就是典型的 Threadlocal 内存泄露场景&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="那为啥不干脆把那个-value-也用弱引用呢"&gt;&lt;a href="#%e9%82%a3%e4%b8%ba%e5%95%a5%e4%b8%8d%e5%b9%b2%e8%84%86%e6%8a%8a%e9%82%a3%e4%b8%aa-value-%e4%b9%9f%e7%94%a8%e5%bc%b1%e5%bc%95%e7%94%a8%e5%91%a2" class="header-anchor"&gt;&lt;/a&gt;那为啥不干脆把那个 value 也用弱引用呢？
&lt;/h3&gt;&lt;p&gt;那样的话 Threadlocal 可能就失去意义了。你想啊，那个 value 是线程真正需要的数据，比如一个数据库连接，如果它也是弱引用，那可能在你正用得好好的时候，突然就被 GC 给回收了。那下次去 get 的时候拿到了可能就是 null 了，即使我没 remove 它。那程序可能就出错了。&lt;strong&gt;所以用强引用是为了保证只要线程逻辑上还需要这个值，并且没显示的remove，它就应该一直在。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是在保证数据可用性和自动内存管理之间做了一个权衡，他选择了优先保证数据，但这个选择就把一部分清理的责任甩给了开发者。&lt;/p&gt;
&lt;h3 id="这对开发者意味着什么-"&gt;&lt;a href="#%e8%bf%99%e5%af%b9%e5%bc%80%e5%8f%91%e8%80%85%e6%84%8f%e5%91%b3%e7%9d%80%e4%bb%80%e4%b9%88-" class="header-anchor"&gt;&lt;/a&gt;这对开发者意味着什么 ？
&lt;/h3&gt;&lt;p&gt;意味着你必须养成一个习惯，非常非常重要的习惯，就是在使用完 Threadlocal 变量之后，一定要最好是在 finally 块里头调用那个 Threadlocal 的 remove 方法。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;terminalpublic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConnectionManager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectionHolder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SQLException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isClosed&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DriverManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;jdbc:mysql://localhost:3306/test&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;closeConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个 remove 方法会把当前线程的 ThreadLocalMap 里跟这个 Threadlocal 实例对应的那个 entry 整个都删掉，这样那个强引用的 value 自然也就没有引用指向它了，下次 GC 就能把它回收了。&lt;/p&gt;
&lt;p&gt;所以关键就是要手动清理，不能偷懒，不能指望它内部那个自动清理机制，&lt;strong&gt;尤其是在线程池这种线程生命周期可能很长的场景下，依赖自动清理风险很大。&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id="java-新版本"&gt;&lt;a href="#java-%e6%96%b0%e7%89%88%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;java 新版本
&lt;/h1&gt;&lt;p&gt;既然 ThreadLocal 有内存泄露的风险，那么后面新的 Java 版本，比如 11、17、21 这些，有没有做些改进，或者提供一些替代方案呢？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;弱引用键、强引用值这个机制，在后面这些版本里基本没变，但是确实有一些改进和变化。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="java-17"&gt;&lt;a href="#java-17" class="header-anchor"&gt;&lt;/a&gt;java 17
&lt;/h2&gt;&lt;p&gt;Java 17 里针对那个公共的 ForkJoinPool，就是 ForkJoinPool 的 common pool，它增加了一个特性，当池里的任务执行完之后，会自动帮你清理掉那个任务线程用过的所有 Threadlocal 值，为这个特定的池缓解了一下风险。但注意，如果你自己创建的 ForkJoinPool 或者普通的线程池，或者直接创建了线程，那还得你自己负责 remove 。&lt;/p&gt;
&lt;h2 id="java-21"&gt;&lt;a href="#java-21" class="header-anchor"&gt;&lt;/a&gt;java 21
&lt;/h2&gt;&lt;p&gt;Java 21 提到的 scoped values ,目前还是预览特性，它提供了一种不同的方式来共享那些需要跟作用域绑定的数据（比如请求处理过程绑定的数据，特别是不可变数据），它的设计理念就是为了避免 Threadlocal 这种需要手动清理的麻烦，用一种结构化的方式来传递和管理，用完自然就没了。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;terminalimport&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;incubator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concurrent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ScopedValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ScopedValueExample&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 声明一个 ScopedValue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ScopedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ScopedValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 使用 ScopedValue.where 绑定值，并在作用域内运行&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ScopedValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Alice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;在作用域内: &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 作用域结束后，值自动消失，不存在泄漏&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// System.out.println(USER.get()); // 会抛 IllegalStateException&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;子方法依然能获取: &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;至于虚拟线程，因为它们被设计成非常轻量级，而且通常生命周期很短，用完就丢了，线程没了它关联的 ThreadLocalMap 自然也就没了，所以长期泄露的风险窗口就大大缩短了。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;terminalpublic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VirtualThreadExample&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ThreadLocal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withInitial&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;未设置&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;InterruptedException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 使用虚拟线程（JDK 21 已经正式支持）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vThread&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofVirtual&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;虚拟线程的数据&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34; -&amp;gt; &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 不需要手动清理，虚拟线程生命周期很短，用完就结束&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 这里 vThread 已经结束，对应的 ThreadLocalMap 已自动销毁&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h1&gt;&lt;p&gt;我们来总结一下 ThreadLocal 这个东西。&lt;/p&gt;
&lt;p&gt;它通过每个线程自己私有的 ThreadLocalMap 实现了线程数据的隔离。挺强大的，在很多场景下很有用，但是它那个弱引用键加上强引用值的设计，就像一把双刃剑，带来了内存泄露的风险，特别是用线程池这种长生命周期的线程池，所以最重要的实践就是要记得用完之后一定在 finally 块里手动调用 remove 来清理。&lt;/p&gt;
&lt;p&gt;虽然新版 Java 针对特定场景，比如公共 ForkJoinPool 做了些自动清理，也提供了像 scoped values 这样的潜在替代方案，但总的来说，理解这个机制，并且承担起主动清理的责任，对开发者来说还是很重要的。&lt;/p&gt;</description></item><item><title>Java老兵的十字路口：坚守还是突围？</title><link>https://xiaobox.github.io/p/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/</link><pubDate>Sat, 29 Mar 2025 05:33:55 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/cover.jpg" alt="Featured image of post Java老兵的十字路口：坚守还是突围？" /&gt;&lt;h2 id="java在技术江湖中的现状稳固基石还是夕阳西下"&gt;&lt;a href="#java%e5%9c%a8%e6%8a%80%e6%9c%af%e6%b1%9f%e6%b9%96%e4%b8%ad%e7%9a%84%e7%8e%b0%e7%8a%b6%e7%a8%b3%e5%9b%ba%e5%9f%ba%e7%9f%b3%e8%bf%98%e6%98%af%e5%a4%95%e9%98%b3%e8%a5%bf%e4%b8%8b" class="header-anchor"&gt;&lt;/a&gt;Java在技术江湖中的现状：稳固基石还是夕阳西下？
&lt;/h2&gt;&lt;p&gt;Java 作为企业级开发的常青树，至今在大量核心系统中扮演着中流砥柱的角色。然而，资深 Java 开发者也明显感受到技术环境的变化。一方面，在银行、政府、互联网巨头等复杂业务场景中，Java 的地位依然稳固；大量遗留系统和核心业务仍运行在 Java 上，短期内很难被完全替换。以优酷的版权管理系统为例，这套长达10年的老系统采用了过时的技术框架，积累了 81万行 Java 代码和大量“没人敢动”的if-else逻辑，可谓技术债累累。像这样的遗留系统，全面重构风险极高，只能在业务推动下逐步演进。因此，在许多传统领域，Java 作为“老码农”的看家本领，仍是不可或缺的基石。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/001-40dd5948.png"&gt;&lt;/p&gt;
&lt;p&gt;另一方面，新兴业务和初创项目对技术栈的选择更加多元。近年Go语言等后起之秀在性能、并发和开发效率上表现出色，成为云原生时代的“宠儿”。不少互联网大厂开始在核心服务中引入 Go：例如谷歌、滴滴、Uber、腾讯等都用 Go 开发高并发、高性能的服务。业界一度流传着“Java 老旧笨重、Go 崭新酷炫”的声音。面对这种冲击，不少资深 Java 工程师难免焦虑：Java 会不会像当年的 COBOL 一样淡出主流舞台？&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/002-28c85ce1.png"&gt;&lt;/p&gt;
&lt;p&gt;事实证明，这种担忧有些过度。Java 拥有数百万开发者和完整生态，并非轻易就能被取代的工具。正如有分析指出，Go 的崛起为行业提供了新选择，但并不是对 Java 的简单替代；两种语言各有优势，未来将长期共存。换言之，Java 依旧是技术江湖里的定海神针，只是江湖规矩变了——老兵们需要适应新玩法。&lt;/p&gt;
&lt;h2 id="java-面临的核心挑战笨重背后的突围"&gt;&lt;a href="#java-%e9%9d%a2%e4%b8%b4%e7%9a%84%e6%a0%b8%e5%bf%83%e6%8c%91%e6%88%98%e7%ac%a8%e9%87%8d%e8%83%8c%e5%90%8e%e7%9a%84%e7%aa%81%e5%9b%b4" class="header-anchor"&gt;&lt;/a&gt;Java 面临的核心挑战：笨重背后的突围
&lt;/h2&gt;&lt;p&gt;资深 Java 开发者在项目实践中遇到的挑战，往往并非语言本身跑不动，而是架构转型带来的“不适感”。近年来微服务、云原生风潮兴起，Java 传统的开发模式在新环境下面临诸多掣肘。&lt;/p&gt;
&lt;h3 id="微服务部署压力"&gt;&lt;a href="#%e5%be%ae%e6%9c%8d%e5%8a%a1%e9%83%a8%e7%bd%b2%e5%8e%8b%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;微服务部署压力
&lt;/h3&gt;&lt;p&gt;将单体应用拆成数十上百的微服务后，每个服务都需要独立部署运行。Java 应用启动慢、内存占用高的问题被放大。在同样功能下，一个简单的 Go 容器镜像可能只有十几MB，而等价的 Java（如采用 Helidon 框架）镜像初始体积高达 1.4GB！即使使用模块化手段缩减JDK体积（JLink可降至150MB左右），Java应用的容器仍显得臃肿。如此高的基础开销让追求极致弹性的微服务架构如临大敌：部署50个 Java 微服务可能需要远超预期的硬件资源，这正是很多团队转向更轻量语言的原因之一。有开发者调侃：“即便Java性能再好，内存占用是别人的 2～10倍，成本账算下来也让人犹豫。”而且在无服务器（Serverless）场景下，Java 冷启动延迟更是令人头疼——函数实例首次启动可能耗时数秒到十几秒。这一问题长期无法回避，直到 AWS 推出 SnapStart 等黑科技，把 Java 函数冷启动时间缩短到毫秒级，才算勉强止血。但需要注意，这类优化是云厂商额外提供的特殊支持，侧面说明 Java 在边缘计算、FaaS 等领域的先天劣势依然存在。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/003-c6bc61f8.png"&gt;&lt;/p&gt;
&lt;h3 id="启动速度与样板代码"&gt;&lt;a href="#%e5%90%af%e5%8a%a8%e9%80%9f%e5%ba%a6%e4%b8%8e%e6%a0%b7%e6%9d%bf%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;启动速度与样板代码
&lt;/h3&gt;&lt;p&gt;“万事开头难”在 Java 世界格外贴切。传统 Java Web 应用往往需要预热 JVM、加载大量类和配置，启动一个服务动辄数十秒甚至几分钟。这在强调弹性伸缩的云环境下难以接受。此外，Java 以模板代码多著称，同样的业务逻辑，用 Java 写可能需要冗长的类定义和 Getter/Setter，而用 Go/Kotlin 等语言则简洁得多。例如，Go 以极简的语法实现高并发，让开发者专注于业务；相比之下，过去的 Java 代码显得繁琐累赘，不少老兵自己也调侃天天在写“体力活”。虽然 Java 近年通过 Lambda、Streams、Records 等特性在不断精简，但是遗留项目中的大量样板代码依旧是维护负担。缺乏某些现代语言特性（如模式匹配、代数数据类型）也使Java在表达某些逻辑时不够优雅。这些痛点促使部分团队尝试用 Kotlin 等 JVM 语言替换 Java，以期获得更简洁的语法和更少的冗余。&lt;/p&gt;
&lt;h3 id="并发与性能困境"&gt;&lt;a href="#%e5%b9%b6%e5%8f%91%e4%b8%8e%e6%80%a7%e8%83%bd%e5%9b%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;并发与性能困境
&lt;/h3&gt;&lt;p&gt;高并发一直是 Java 的强项，但实现方式却日益受到挑战。传统 Java 使用操作系统线程实现并发，每个线程都对应一定的内存和调度开销，在大规模场景下显得“沉重”。为绕过这个瓶颈，过去几年兴起了基于 Reactive 异步编程的微服务框架，通过单线程事件循环避免线程阻塞。然而异步风格代码复杂度高、调试困难，让许多工程师“叫苦不迭”。好消息是，JDK 19/20 引入了虚拟线程（Project Loom）并在 JDK 21 成为正式特性。虚拟线程是由 JVM 管理的超轻量线程，实现了 Go 协程式的并发模型。这意味着开发者可以用以往同步阻塞的简单代码，实现过去需要复杂回调/响应式才能处理的高并发任务。正如 Java 架构师 Brian Goetz 所言：Loom 的出现有望“一举终结Reactive编程的必要”——因为过去Reactive是为解决线程不足的权宜之计。虚拟线程让我们能够创建成千上万个并发任务而不必担心线程耗尽，大幅降低了编写和维护高并发代码的心智负担。然而，新事物也伴随不确定性：老项目若迁移到虚拟线程模型，需要评估线程本地变量、同步机制等是否还能正常工作；调优方式也与传统线程有所不同。目前虚拟线程虽强大，但毕竟是新特性，在大型生产环境中的考验还不充分。Java 老兵们既期待它带来性能飞跃，也需要保持一份观望和谨慎。&lt;/p&gt;
&lt;h3 id="graalvm-与原生执行"&gt;&lt;a href="#graalvm-%e4%b8%8e%e5%8e%9f%e7%94%9f%e6%89%a7%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;GraalVM 与原生执行
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/004-3147eb4e.png"&gt;&lt;/p&gt;
&lt;p&gt;为了解决启动慢、内存高的问题，Java 社区近年另一“大招”是 GraalVM 原生镜像。通过提前编译(AOT)，可以将 Java 应用直接打包成本地可执行文件，启动时间和内存占用都有数量级的优化。这项技术被视为让 Java 重返边缘计算和 Serverless 舞台的希望：原生镜像下，一个 Spring Boot 微服务的“Hello World”容器镜像可小到 ~几十MB；运行时不需要JVM，冷启动延迟大幅降低。实际测试中，采用 GraalVM 原生镜像的 Java 服务在某些基准下性能甚至超越 Go：平均延迟仅0.25毫秒，每秒处理事务达到82426次，吞吐率是 Go 实现的两倍多！这种结果令人振奋，仿佛看到了 Java 打了一场漂亮的翻身仗。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/005-846f3af1.png"&gt;&lt;/p&gt;
&lt;p&gt;然而，理想很丰满，现实有时比较骨感。将复杂应用迁移到 GraalVM 原生镜像并非易事。例如，反射、动态代理等机制需要额外配置支持，许多成熟库在AOT编译下可能行为异常。构建原生镜像的过程也比较繁琐，往往需要调整代码、引入特定插件，并忍受较长的编译时间。调试诊断也更具挑战——原生应用无法使用 JVM 的丰富调试工具，需要新的手段排查问题。此外，引入 GraalVM 还意味着团队需要掌握一套新的知识体系。在的总结中作者就指出：“将 Spring Boot 应用打包为 Native 镜像并非没有挑战”，直接迁移复杂项目可能遇到种种坑，需要开发者充分评估和测试。因此，GraalVM 不是万能灵药，而是有门槛的新武器：用得好，Java 如虎添翼；用不好，反而可能引入新的不稳定因素。&lt;/p&gt;
&lt;p&gt;综上，资深 Java 开发者面对的不是“Java 不行了”，而是如何让 Java 行得更轻、更快、更优雅。JVM 社区显然没有躺在功劳簿上吃老本，而是在微服务、云原生时代积极求变。从 Spring Boot 3 对原生镜像的支持，到 JDK 连续的功能升级（如Records、Pattern Matching等），Java 正在努力破除“笨重”的刻板印象。老兵们需要做的，是与时俱进地拥抱这些变化，用新工具、新思路来武装自己的Java技能库。&lt;/p&gt;
&lt;h2 id="用舍之道哪些场景放弃-java哪些场景坚持-java"&gt;&lt;a href="#%e7%94%a8%e8%88%8d%e4%b9%8b%e9%81%93%e5%93%aa%e4%ba%9b%e5%9c%ba%e6%99%af%e6%94%be%e5%bc%83-java%e5%93%aa%e4%ba%9b%e5%9c%ba%e6%99%af%e5%9d%9a%e6%8c%81-java" class="header-anchor"&gt;&lt;/a&gt;用舍之道：哪些场景放弃 Java，哪些场景坚持 Java？
&lt;/h2&gt;&lt;p&gt;技术选型从来都不是非黑即白，对于 Java 的去留更是如此。究竟在哪些业务场景下应该考虑放弃 Java？哪些场景下 Java 仍是首选？结合真实案例和趋势，我们可以做出以下判断：&lt;/p&gt;
&lt;h3 id="场景一边缘计算与serverless--谨慎使用-java"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%b8%80%e8%be%b9%e7%bc%98%e8%ae%a1%e7%ae%97%e4%b8%8eserverless--%e8%b0%a8%e6%85%8e%e4%bd%bf%e7%94%a8-java" class="header-anchor"&gt;&lt;/a&gt;场景一：边缘计算与Serverless – 谨慎使用 Java。
&lt;/h3&gt;&lt;p&gt;对于运行环境受限、对启动延迟敏感的场景，选择 Java 需要非常慎重。典型如物联网设备、边缘网关、函数计算等，这些环境往往内存有限且要求冷启动极快。在这些场合，运行一个庞大的 JVM 显然不如直接使用原生语言（C/C++、Rust）或轻量脚本语言（JavaScript、Python）来得高效。过去不少团队在实现事件驱动的小型服务时，就倾向于用 Node.js 或 Python 编写——不是因为Java不能实现功能，而是因为Java在每次调用都要“热身”的开销让人难以忍受。虽然有 GraalVM Native Image 可以大幅优化，但对小型团队而言，引入它的复杂度可能得不偿失。因此，对于边缘和无服务函数等应用，除非有充足理由和相应优化手段，否则倾向于选择更轻便的技术栈。当然，规则也非绝对：如果业务逻辑需要调用大量现有的 Java 类库（例如进行某种算法运算，而相关库只有Java实现），那么即便在 Serverless 环境下通过原生镜像等方式使用 Java 也是可以考虑的。总的来说，在这些场景，“能不用Java就不用”是较为实际的指导原则。&lt;/p&gt;
&lt;h3 id="场景二高性能微服务--视情况取舍"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%ba%8c%e9%ab%98%e6%80%a7%e8%83%bd%e5%be%ae%e6%9c%8d%e5%8a%a1--%e8%a7%86%e6%83%85%e5%86%b5%e5%8f%96%e8%88%8d" class="header-anchor"&gt;&lt;/a&gt;场景二：高性能微服务 – 视情况取舍
&lt;/h3&gt;&lt;p&gt;在互联网分布式系统中，每种语言都有用武之地。如果团队主要目标是极致的性能和资源利用率，并且成员对 Go/Rust 等语言驾轻就熟，那么把部分微服务用新语言实现未尝不可。例如某些网关服务、实时通信服务，行业里确有用 Rust 或 Go 重写后延迟降低、内存减半的成功案例。特别是低延迟、高并发的基础设施组件（消息队列、代理服务器等），很多开源项目早就避开 Java 转投 Go/Rust 怀抱，这是技术基因所致（Java 更擅长业务逻辑，系统编程领域C系语言传统更强）。但是，对于业务逻辑复杂的微服务，Java 仍然具有难以替代的优势：强大的生态提供了各种中间件客户端、成熟的 ORM 和事务框架、安全完备的验证和监控工具等等。这些“全家桶”式的支持使Java在开发业务系统时如鱼得水，大大减少了造轮子的成本。如果纯粹为了追新把此类服务改用另一种语言，可能会发现需要重建许多Java自带的轮子，得不偿失。因此，我们的立场是：对性能极限有追求的核心组件，可以考虑非Java实现以挖掘潜力；但大多数微服务尤其是业务导向的微服务，Java 依然是稳妥且高效的选择。况且随着Quarkus、Micronaut等专为云环境优化的Java框架出现，以及JVM自身的持续优化，Java 微服务的“笨重”正在被削平。正如某次测试所示，在较大的机器上，Java 的吞吐甚至可与 Go 持平甚至略胜一筹——只要用对了方式，Java 完全能胜任高性能微服务。&lt;/p&gt;
&lt;h3 id="场景三大型核心系统--坚定拥抱-java"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%b8%89%e5%a4%a7%e5%9e%8b%e6%a0%b8%e5%bf%83%e7%b3%bb%e7%bb%9f--%e5%9d%9a%e5%ae%9a%e6%8b%a5%e6%8a%b1-java" class="header-anchor"&gt;&lt;/a&gt;场景三：大型核心系统 – 坚定拥抱 Java
&lt;/h3&gt;&lt;p&gt;对于那些 复杂度高、生命周期长、需要强一致性和可靠性的核心业务，Java 无疑仍是值得长期信赖的编程语言。例如银行的核心账务系统、航空公司的订票系统、阿里的电商交易中台等，这些系统往往经历多年演化，业务规则繁多且严谨，需要大量业内验证过的中间件支撑。Java 的严格类型体系和成熟框架在这里如鱼得水。特别是在金融、政府等对稳定性要求极高的领域，“Java + 大型商用中间件”的组合几乎是默认标配。从技术债的角度考虑，这类系统虽然也面临老旧架构的问题，但重构时通常还是在 Java 体系内升级（比如从 Struts 升级到 Spring Boot，或引入分布式事务框架等），而不会轻易迁移到一门全新的语言上。这不仅因为重写成本高，更因为 Java 多年沉淀的安全性和可靠性难以替代。可以说，在复杂业务长跑中，Java 是一匹稳健的“长途马”，跑得也许不算最快，但足够稳当，生态中现成的工具能够覆盖方方面面，让架构师和开发者更安心。基于这些原因，我们坚定认为：在复杂业务和核心系统场景下，坚持使用 Java 是明智之举。即便引入新的技术插件，也是作为补充而非颠覆，比如用 Python 做小部分AI预测，再把结果喂给Java主系统等等。Java 老兵在这些战场上大可发挥深厚经验，将系统设计得健壮且易于维护，为业务保驾护航。&lt;/p&gt;
&lt;p&gt;归纳来说，用舍有道，视需而定：Java 并非万能，同样也远未过时。关键在于根据项目需求选择最合适的工具。在前沿领域不妨多尝试新语言新架构，以保持竞争力；而在关系到企业命脉的长线工程上，Java 依然值得我们托付。&lt;/p&gt;
&lt;h2 id="java老兵的自我进化坚守阵地or华丽转型"&gt;&lt;a href="#java%e8%80%81%e5%85%b5%e7%9a%84%e8%87%aa%e6%88%91%e8%bf%9b%e5%8c%96%e5%9d%9a%e5%ae%88%e9%98%b5%e5%9c%b0or%e5%8d%8e%e4%b8%bd%e8%bd%ac%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;Java老兵的自我进化：坚守阵地or华丽转型？
&lt;/h2&gt;&lt;p&gt;面对风起云涌的技术浪潮，10年以上经验的 Java 老将们该何去何从？是固守舒适圈，还是勇敢拓展边界？以下几点建议或许对处在十字路口的你有所启发：&lt;/p&gt;
&lt;h3 id="拥抱java新特性跟上生态演进"&gt;&lt;a href="#%e6%8b%a5%e6%8a%b1java%e6%96%b0%e7%89%b9%e6%80%a7%e8%b7%9f%e4%b8%8a%e7%94%9f%e6%80%81%e6%bc%94%e8%bf%9b" class="header-anchor"&gt;&lt;/a&gt;拥抱Java新特性，跟上生态演进
&lt;/h3&gt;&lt;p&gt;不要认为“学了十几年Java就没有新东西可学”。相反，Java生态在飞速更新，每年两个版本迭代。老兵们应该主动学习 JDK近几版的新功能（如Records、Sealed Class、Pattern Matching、虚拟线程等），这些特性能显著改善代码质量和性能，使你的技能焕发新生。例如，试着用 Loom 虚拟线程改造一个老的并发模块，体会一下开发模式的简化；或者研究 GraalVM 如何将现有服务无缝打包为原生镜像，了解其中的限制和调优手段。拥抱新技术不仅能提升生产力，也向团队展示了你与时俱进的技术热情。作为Java老兵，切忌固步自封——持续学习是对抗职业倦怠和时代冲击的最好武器。&lt;/p&gt;
&lt;h3 id="拓展多元技能栈成为t型人才"&gt;&lt;a href="#%e6%8b%93%e5%b1%95%e5%a4%9a%e5%85%83%e6%8a%80%e8%83%bd%e6%a0%88%e6%88%90%e4%b8%bat%e5%9e%8b%e4%ba%ba%e6%89%8d" class="header-anchor"&gt;&lt;/a&gt;拓展多元技能栈，成为“T型”人才
&lt;/h3&gt;&lt;p&gt;在保持Java优势的同时，建议横向拓展一到两门其它语言或领域技能。比如，可以尝试学习 Go 或 Python，用它们做些小项目，体会不同语言在思维模型上的差异。再比如，深入了解一下前端技术或移动开发，哪怕不做前端，也能与前端同事更高效协作。这种“T”字型的技能结构（既有一门精深的主力技术，又对相关技术有所涉猎）将使你在团队中更具价值。很多架构师在成为架构师前，都曾是精通数门语言、熟悉多种数据库和中间件的全能型工程师。对Java老兵来说，学习一门新语言还能帮助跳出现有思维框架，把新理念反哺到Java日常开发中。例如，借鉴函数式编程思想优化Java代码，或者用脚本语言编写自动化工具提升开发效率。多元化的技能还为你提供了职业备胎：万一某天真的不想写Java了，你在其他领域的积累也足以支撑转型，不至于手足无措。&lt;/p&gt;
&lt;h3 id="深入业务和架构提升不可替代性"&gt;&lt;a href="#%e6%b7%b1%e5%85%a5%e4%b8%9a%e5%8a%a1%e5%92%8c%e6%9e%b6%e6%9e%84%e6%8f%90%e5%8d%87%e4%b8%8d%e5%8f%af%e6%9b%bf%e4%bb%a3%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;深入业务和架构，提升不可替代性
&lt;/h3&gt;&lt;p&gt;随着工作年限增长，“懂业务、能设计”往往比单纯的编码能力更重要。Java老兵应该充分利用在一个行业浸润多年的经验，去深入理解业务领域 的本质问题，把握业务发展方向。将业务洞察与技术方案相结合，主动参与系统架构设计和重大技术选型，这会让你成为团队中不可或缺的核心人物。很多时候，业务专家+技术专家的复合型人才，比仅仅精通某种语法的程序员更有竞争力。如果你已经是某核心系统的Owner，不妨尝试推进架构优化和性能提升项目，展示自己在宏观层面的掌控力。同时，培养自己的系统设计能力，多研究业界大型系统的架构案例，学习它们如何权衡取舍。当你能从容驾驭分布式事务、异地多活、CQRS 等架构模式时，你的价值早已超越“Java 工程师”的范畴，而成为真正的技术专家。这种升级，无论未来Java的热度如何，都能让你的职业生涯保持上升。&lt;/p&gt;
&lt;h3 id="考虑转型技术管理或其他新领域"&gt;&lt;a href="#%e8%80%83%e8%99%91%e8%bd%ac%e5%9e%8b%e6%8a%80%e6%9c%af%e7%ae%a1%e7%90%86%e6%88%96%e5%85%b6%e4%bb%96%e6%96%b0%e9%a2%86%e5%9f%9f" class="header-anchor"&gt;&lt;/a&gt;考虑转型技术管理或其他新领域
&lt;/h3&gt;&lt;p&gt;并非每个人都要永远写代码。工作十年以上后，你也可以根据兴趣转型，选择最适合自己的道路。如果你热衷带团队和项目把控，可以逐步走向 技术管理 岗位，担任Team Leader、技术经理甚至CTO，把多年经验用于培养新人和决策把关。很多Java老兵在这一阶段选择带领团队，既可传承自己的开发哲学，又能获得管理成就感。又或者，你对某些新兴领域情有独钟，例如 人工智能、大数据、安全 等，不妨利用业余时间学习相关知识，寻求内部调岗或外部机会。资深程序员转做产品经理、解决方案架构师的例子也屡见不鲜——只要有心，完全可以跳出演员阵容，转到幕后编剧或导演的位置上。当然，做出转型决定前需要评估清楚：你的核心竞争力是什么，新领域是否真心喜欢，从头开始是否有心理准备。转型不是逃避，而是为了更长远的发展。无论选择深耕Java栈还是开拓新跑道，持续的学习和热情都是关键驱动力。&lt;/p&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;想对每一位焦虑中的Java老兵说：技术江湖瞬息万变，但真正的资深工程师价值从不局限于某种语法。Java 之父 James Gosling 曾打比方说：“Java就像一辆可靠的卡车”，或许它没有跑车那样光鲜，但能载着重载货物稳稳前行。这辆卡车如今也在不断改装升级，动力和油耗都在改进。我们作为司机，要做的不是弃车而逃，而是练就更高超的驾驶技巧，并且学会在不同道路上换合适的交通工具。坚守初心并不代表故步自封，拥抱变化也不意味着全盘否定过去。当我们既掌握了Java这门老牌利器，又勇于学习新招式、新套路，在变化的浪潮中依然能找到自己的方向和节奏。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/006-0c6fa2fa.png"&gt;&lt;/p&gt;
&lt;p&gt;10+年开发生涯沉淀下来的经验与智慧，是宝贵的财富。无论Java的流行曲线如何波动，真正优秀的工程师都会不断进化，拓展自己的边界。在这个过程中，我们既要有克制冷静的思考，看清技术演进的本质；也要保持对编程的热爱，不忘初心地享受技术创造的乐趣。愿每一位Java老兵都能在时代洪流中找到属于自己的位置：该出手时果断出手，该坚守时稳如磐石，在新的十年里续写属于你的传奇。&lt;/p&gt;</description></item><item><title>Redis6.0 以后为什么使用了多线程？</title><link>https://xiaobox.github.io/p/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/</link><pubDate>Mon, 18 Nov 2024 02:04:32 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/cover.jpg" alt="Featured image of post Redis6.0 以后为什么使用了多线程？" /&gt;&lt;p&gt;Redis 所谓的单线程并不是所有工作都是只有一个线程在执行，而是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的，Redis 在处理客户端的请求时包括获取 (socket 读）、解析、执行、内容返回 (socket 写） 等都由一个顺序串行的主线程处理。&lt;/p&gt;
&lt;p&gt;这就是所谓的“&lt;strong&gt;单线程&lt;/strong&gt;”。这也是 Redis 对外提供键值存储服务的主要流程。
由于 Redis 在处理命令的时候是单线程作业的，所以会有一个 Socket 队列，每一个到达的服务端命令来了之后都不会马上被执行，而是进入队列，然后被线程的事件分发器逐个执行。如下图：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/001-b7c0094d.png"&gt;&lt;/p&gt;
&lt;p&gt;至于 Redis 的其他功能， 比如持久化、异步删除、集群数据同步等等，其实是由额外的线程执行的。 可以这么说，Redis 工作线程是单线程的。但是在 4.0 之后，对于整个 Redis 服务来说，还是多线程运作的。&lt;/p&gt;
&lt;h2 id="60-之前为什么要使用单线程"&gt;&lt;a href="#60-%e4%b9%8b%e5%89%8d%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e4%bd%bf%e7%94%a8%e5%8d%95%e7%ba%bf%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;6.0 之前为什么要使用单线程
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/002-55bc246f.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在使用 Redis 时，Redis 主要受限是在内存和网络上，CPU 几乎没有性能瓶颈的问题。&lt;/li&gt;
&lt;li&gt;以 Linux 系统为例子，在 Linux 系统上 Redis 通过 pipelining 可以处理 100w 个请求每秒，而应用程序的计算复杂度主要是 O(N) 或 O(log(N)) ，不会消耗太多 CPU。&lt;/li&gt;
&lt;li&gt;使用了单线程后，提高了可维护性。多线程模型在某些方面表现优异，却增加了程序执行顺序的不确定性，并且带来了并发读写的一系列问题，增加了系统复杂度。同时因为线程切换、加解锁，甚至死锁，造成一定的性能损耗。&lt;/li&gt;
&lt;li&gt;Redis 通过 AE 事件模型以及 IO 多路复用等技术，拥有超高的处理性能，因此没有使用多线程的必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="60-之后的多线程主要解决什么问题"&gt;&lt;a href="#60-%e4%b9%8b%e5%90%8e%e7%9a%84%e5%a4%9a%e7%ba%bf%e7%a8%8b%e4%b8%bb%e8%a6%81%e8%a7%a3%e5%86%b3%e4%bb%80%e4%b9%88%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;6.0 之后的多线程主要解决什么问题
&lt;/h2&gt;&lt;p&gt;近年来底层网络硬件性能越来越好，Redis 的性能瓶颈逐渐体现在网络 I/O 的读写上，单个线程处理网络 I/O 读写的速度跟不上底层网络硬件执行的速度。&lt;/p&gt;
&lt;p&gt;Redis 在处理网络数据时，调用 epoll 的过程是阻塞的，这个过程会阻塞线程。如果并发量很高，达到万级别的 QPS，就会形成瓶颈，影响整体吞吐能力&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/003-e1c54fcd.png"&gt;&lt;/p&gt;
&lt;p&gt;既然读写网络的 read/write 系统调用占用了 Redis 执行期间大部分 CPU 时间，那么要想真正做到提速，必须改善网络 IO 性能。我们可以从这两个方面来优化：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提高网络 IO 性能，典型实现方式比如使用 DPDK 来替代内核网络栈的方式&lt;/li&gt;
&lt;li&gt;使用多线程，这样可以充分利用多核 CPU，同类实现案例比如 Memcached。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;协议栈优化的这种方式跟 Redis 关系不大，所以最便捷高效的方式就是支持多线程。总结起来，redis 支持多线程就是以下两个原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以充分利用服务器 CPU 的多核资源，而主线程明显只能利用一个&lt;/li&gt;
&lt;li&gt;多线程任务可以分摊 Redis 同步 IO 读写负荷，降低耗时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6.0 版本优化之后，主线程和多线程网络 IO 的执行流程如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-18-redis6-0-yi-hou-wei-shen-me-shi-yong-le-duo-xian-cheng/004-51bc3556.png"&gt;&lt;/p&gt;
&lt;p&gt;具体步骤如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主线程建立连接，并接受数据，并将获取的 socket 数据放入等待队列；&lt;/li&gt;
&lt;li&gt;通过轮询的方式将 socket 读取出来并分配给 IO 线程；&lt;/li&gt;
&lt;li&gt;之后主线程保持阻塞，一直等到 IO 线程完成 socket 读取和解析；&lt;/li&gt;
&lt;li&gt;I/O 线程读取和解析完成之后，返回给主线程 ，主线程开始执行 Redis 命令；&lt;/li&gt;
&lt;li&gt;执行完 Redis 命令后，主线程阻塞，直到 IO 线程完成 结果回写到 socket 的工作；&lt;/li&gt;
&lt;li&gt;主线程清空已完成的队列，等待客户端新的请求。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本质上是将主线程 IO 读写的这个操作 独立出来，单独交给一个 I/O 线程组处理。
这样多个 socket 读写可以并行执行，整体效率也就提高了。同时注意 Redis 命令还是主线程串行执行。&lt;/p&gt;
&lt;p&gt;利用多核来分担 I/O 读写负荷。在事件处理线程每次获取到可读事件时，会将所有就绪的读事件分配给 I/O 线程，并进行等待，在所有 I/O 线程完成读操作后，事件处理线程开始执行任务处理，在处理结束后，同样将写事件分配给 I/O 线程，等待所有 I/O 线程完成写操作。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;int handleClientsWithPendingReadsUsingThreads(void) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; /* Distribute the clients across N different lists. */
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; listIter li;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; listNode *ln;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; listRewind(server.clients_pending_read,&amp;amp;li);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; int item_id = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; // 将等待处理的客户端分配给 I/O 线程
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; while((ln = listNext(&amp;amp;li))) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; client *c = listNodeValue(ln);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; int target_id = item_id % server.io_threads_num;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; listAddNodeTail(io_threads_list[target_id],c);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; item_id++;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; /* Wait for all the other threads to end their work. */
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; // 轮训等待所有 I/O 线程处理完
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; while(1) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; unsigned long pending = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; for (int j = 1; j &amp;lt; server.io_threads_num; j++)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; pending += io_threads_pending[j];
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; if (pending == 0) break;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt; return processed;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;本质上是利用多核的多线程让多个 IO 的读写加速。&lt;/p&gt;
&lt;h3 id="局限性"&gt;&lt;a href="#%e5%b1%80%e9%99%90%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;局限性
&lt;/h3&gt;&lt;p&gt;6.0 版本的多线程并非彻底的多线程，I/O 线程只能同时执行读或者同时执行写操作，期间事件处理线程一直处于等待状态，并非流水线模型，有很多轮训等待开销。&lt;/p&gt;</description></item><item><title>Java 集合 API 的改进</title><link>https://xiaobox.github.io/p/2024-11-12-java-ji-he-api-de-gai-jin/</link><pubDate>Tue, 12 Nov 2024 04:13:20 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-11-12-java-ji-he-api-de-gai-jin/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-12-java-ji-he-api-de-gai-jin/cover.jpg" alt="Featured image of post Java 集合 API 的改进" /&gt;&lt;h2 id="简介"&gt;&lt;a href="#%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;&lt;/a&gt;简介
&lt;/h2&gt;&lt;p&gt;本文我们将探讨不同 jdk 版本中各类的起源，以及新引入的类和接口背后的目的。我们将分析之前版本存在的问题，以及为何需要引入新的类或接口。此外，我们还将介绍集合类和接口中的新特性。文章将逐一解答这些问题。&lt;/p&gt;
&lt;p&gt;我们将逐步学习 Java 集合类的优化过程，并按版本逐一对比分析。主要讨论的焦点将包括 JDK 1.0、1.2、1.4、1.5、1.6、1.8、9、10、11 和 21 版本的 Java 集合功能&lt;/p&gt;
&lt;h2 id="java-集合-api-的改进"&gt;&lt;a href="#java-%e9%9b%86%e5%90%88-api-%e7%9a%84%e6%94%b9%e8%bf%9b" class="header-anchor"&gt;&lt;/a&gt;Java 集合 API 的改进
&lt;/h2&gt;&lt;p&gt;Java 集合 API 在多年中经历了显著改进，引入了新功能、增强和优化，以提高开发者的生产力、改善性能，并适应修订的编程模式和需求。它将帮助开发者利用 Java 集合的力量构建更健壮、高效和可维护的应用程序。&lt;/p&gt;
&lt;h2 id="jdk-10-中的集合类"&gt;&lt;a href="#jdk-10-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.0 中的集合类
&lt;/h2&gt;&lt;p&gt;在 JDK 1.0 中，有四个类 &lt;code&gt;Vector&lt;/code&gt;、&lt;code&gt;Stack&lt;/code&gt;、&lt;code&gt;Hashtable&lt;/code&gt; 和 &lt;code&gt;Properties&lt;/code&gt;。此外，还有一个名为“&lt;code&gt;Enumeration&lt;/code&gt;”的接口，用于以简单的方式遍历值。进一步分类，Stack 是 Vector 的子类，Properties 是 Hashtable 的子类。&lt;/p&gt;
&lt;h3 id="vector-类的问题"&gt;&lt;a href="#vector-%e7%b1%bb%e7%9a%84%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;Vector 类的问题
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Vector 是线程安全的，即 Vector 中的所有方法都是同步的。因此，它不适合单线程环境。&lt;/li&gt;
&lt;li&gt;由于它在内部基于数组工作，插入和删除操作非常慢。&lt;/li&gt;
&lt;li&gt;它允许在其中添加重复元素&lt;/li&gt;
&lt;li&gt;无法按顺序存储元素&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="hashtable-类的问题"&gt;&lt;a href="#hashtable-%e7%b1%bb%e7%9a%84%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;Hashtable 类的问题
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Hashtable 是线程安全的，即 Hashtable 中的所有方法都是同步的。因此，它不适合单线程环境。&lt;/li&gt;
&lt;li&gt;Hashtable 无法按顺序存储条目&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="enumeration-的问题"&gt;&lt;a href="#enumeration-%e7%9a%84%e9%97%ae%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;Enumeration 的问题
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;无法删除元素且方法名称过长&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jdk-12-中的集合类"&gt;&lt;a href="#jdk-12-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.2 中的集合类
&lt;/h2&gt;&lt;p&gt;在 JDK 1.2 中，Sun Micro-system 引入了 &lt;code&gt;ArrayList&lt;/code&gt;、&lt;code&gt;LinkedList&lt;/code&gt;、&lt;code&gt;HashSet&lt;/code&gt;、&lt;code&gt;TreeSet&lt;/code&gt;、&lt;code&gt;HashMap&lt;/code&gt;、&lt;code&gt;TreeMap&lt;/code&gt;、&lt;code&gt;Iterator&lt;/code&gt; 和 &lt;code&gt;ListIterator&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ArrayList：用于提供单线程环境下的解决方案，因为 ArrayList 中的方法不是同步的。&lt;/li&gt;
&lt;li&gt;LinkedList 用于提供更快的元素插入和删除。&lt;/li&gt;
&lt;li&gt;HashSet：不允许有重复元素。&lt;/li&gt;
&lt;li&gt;TreeSet：用于按排序顺序存储元素。&lt;/li&gt;
&lt;li&gt;HashMap：提供单线程环境下的解决方案，因为 HashMap 中的方法不是同步的。&lt;/li&gt;
&lt;li&gt;TreeMap：用于按顺序存储键值对。&lt;/li&gt;
&lt;li&gt;Iterator：用于解决枚举问题。同时还有一个专门处理列表的类 ListIterator。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;HashSet 的问题&lt;/strong&gt;：它不能保持插入顺序，即它不会按照元素添加到集合中的顺序存储元素。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HashMap 的问题&lt;/strong&gt;：像 HashSet 一样，它不能保持插入顺序。&lt;/p&gt;
&lt;h2 id="jdk-14-中的集合类"&gt;&lt;a href="#jdk-14-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.4 中的集合类
&lt;/h2&gt;&lt;p&gt;在 JDK 1.2 中，Sun Microsystems 引入了 &lt;code&gt;LinkedHashSet&lt;/code&gt; 和 &lt;code&gt;LinkedHashMap&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LinkedHashSet：用于解决 HashSet 中插入顺序的问题。它按照元素添加到集合中的顺序存储元素。&lt;/li&gt;
&lt;li&gt;LinkedHashMap：用于解决 HashMap 中插入顺序的问题。它还按照元素添加到集合中的顺序存储元素。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jdk-15-中的集合类"&gt;&lt;a href="#jdk-15-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.5 中的集合类
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;for-Each 循环：作为替代迭代器进行迭代的另一种方法&lt;/li&gt;
&lt;li&gt;CopyOnWriteArrayList：引入以允许在修改底层列表的情况下安全地迭代元素。&lt;/li&gt;
&lt;li&gt;CopyOnWriteArraySet：它使用内部 CopyOnWriteArrayList 进行所有操作。因此，它具有与该列表相同的基本属性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jdk-16-中的集合类"&gt;&lt;a href="#jdk-16-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.6 中的集合类
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;NavigableSet：作为扩展了导航方法的有序集合，用于报告给定搜索目标的最近匹配。&lt;/li&gt;
&lt;li&gt;NavigableMap：作为扩展了导航方法的 SortedMap，返回给定搜索目标的最近匹配项。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-12-java-ji-he-api-de-gai-jin/001-b283acb5.jpg"&gt;&lt;/p&gt;
&lt;h2 id="jdk-18-中的集合类"&gt;&lt;a href="#jdk-18-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;JDK 1.8 中的集合类
&lt;/h2&gt;&lt;p&gt;Java 集合框架也有新更新，以支持 lambda 表达式、流和聚合操作。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;stream() 作为父接口 Collection 的默认方法：返回一个以该集合为源的顺序 Stream。&lt;/li&gt;
&lt;li&gt;parallelStream() 作为父接口 Collection 的默认方法：返回一个可能并行的 Stream，以这个集合作为其源。&lt;/li&gt;
&lt;li&gt;spliterator() 作为父接口 Collection 的一个默认方法：创建一个遍历此集合中元素的 Spliterator&lt;/li&gt;
&lt;li&gt;removeIf(Predicate filter) 作为父接口 Collection 的默认方法：移除满足给定谓词的所有元素。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同样重要的是，这里的一个显著点是所有新添加的方法都是接口 Collection 内部的默认方法。这是使用默认方法的最佳示例。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-12-java-ji-he-api-de-gai-jin/002-bf3a4631.png"&gt;&lt;/p&gt;
&lt;h2 id="java-9-中的集合增强"&gt;&lt;a href="#java-9-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e5%a2%9e%e5%bc%ba" class="header-anchor"&gt;&lt;/a&gt;Java 9 中的集合增强
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;新增用于创建不可变列表、集合和映射的 of() 静态工厂方法介绍。这些方法包括：&lt;code&gt;List.of()&lt;/code&gt;, &lt;code&gt;Set.of()&lt;/code&gt;, &lt;code&gt;Map.of()&lt;/code&gt;, &lt;code&gt;Map.ofEntries()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Arrays.mismatch()：新增方法以查找两个数组中第一个不匹配的索引。&lt;/li&gt;
&lt;li&gt;Arrays.compare()：添加了新方法来比较提供的两个数组中的元素。&lt;/li&gt;
&lt;li&gt;为 Arrays.equals() 添加了更多重载方法。&lt;/li&gt;
&lt;li&gt;Enumeration.asIterator()：添加了返回 java.util.Iterator 实例的新方法。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外，在 &lt;code&gt;Stream&lt;/code&gt; API 中添加了一些方法，如 dropWhile、takeWhile 和 ofNullable。&lt;/p&gt;
&lt;h2 id="java-10-中的集合增强"&gt;&lt;a href="#java-10-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e5%a2%9e%e5%bc%ba" class="header-anchor"&gt;&lt;/a&gt;Java 10 中的集合增强
&lt;/h2&gt;&lt;p&gt;引入了 List.copyOf()、Set.copyOf() 和 Map.copyOf()，用于创建现有集合的不变副本。&lt;/p&gt;
&lt;h2 id="java-11-中的集合增强"&gt;&lt;a href="#java-11-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e5%a2%9e%e5%bc%ba" class="header-anchor"&gt;&lt;/a&gt;Java 11 中的集合增强
&lt;/h2&gt;&lt;p&gt;Collection.toArray(IntFunction)：添加了新的默认方法，允许将集合的元素转移到新创建的具有所需运行时类型的数组中。新方法是现有 toArray(…) 方法的重载变体。&lt;/p&gt;
&lt;h2 id="java-21-中的集合增强"&gt;&lt;a href="#java-21-%e4%b8%ad%e7%9a%84%e9%9b%86%e5%90%88%e5%a2%9e%e5%bc%ba" class="header-anchor"&gt;&lt;/a&gt;Java 21 中的集合增强
&lt;/h2&gt;&lt;p&gt;Java 21 在集合框架中引入了三个新接口：&lt;code&gt;SequencedCollection&lt;/code&gt;、&lt;code&gt;SequencedSet&lt;/code&gt; 和 &lt;code&gt;SequencedMap&lt;/code&gt;。这些新的集合接口通过新库提供的默认方法，使我们能够访问其第一个和最后一个元素。该功能还允许我们通过简单的调用方法来获取集合的反转视图。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-11-12-java-ji-he-api-de-gai-jin/003-e53f56fa.png"&gt;&lt;/p&gt;
&lt;h3 id="sequencedcollection--序列集合"&gt;&lt;a href="#sequencedcollection--%e5%ba%8f%e5%88%97%e9%9b%86%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;SequencedCollection 序列集合
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;default void addFirst(E e)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;default void addLast(E e)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;default E getFirst()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;default E getLast()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;default E removeFirst()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;default E removeLast()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;SequencedCollection&amp;lt;E&amp;gt; reversed()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sequencedset-序列集合"&gt;&lt;a href="#sequencedset-%e5%ba%8f%e5%88%97%e9%9b%86%e5%90%88" class="header-anchor"&gt;&lt;/a&gt;SequencedSet 序列集合
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;SequencedSet&amp;lt;E&amp;gt; reversed()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="sequencedmap-序列映射"&gt;&lt;a href="#sequencedmap-%e5%ba%8f%e5%88%97%e6%98%a0%e5%b0%84" class="header-anchor"&gt;&lt;/a&gt;SequencedMap 序列映射
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;default Map.Entry&amp;lt;K,V&amp;gt; firstEntry()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;default Map.Entry&amp;lt;K,V&amp;gt; lastEntry()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;default Map.Entry&amp;lt;K,V&amp;gt; pollFirstEntry()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;default Map.Entry&amp;lt;K,V&amp;gt; pollLastEntry()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;default V putFirst(K k, V v)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;default V putLast(K k, V v)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;SequencedMap&amp;lt;K,V&amp;gt; reversed()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;default SequencedSet&amp;lt;Map.Entry&amp;lt;K,V&amp;gt;&amp;gt; sequencedEntrySet()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;default SequencedSet&amp;lt;K&amp;gt; sequencedKeySet()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;default SequencedCollection&amp;lt;V&amp;gt; sequencedValues()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>REST 与 gRPC 的详细比较</title><link>https://xiaobox.github.io/p/2024-09-04-rest-yu-grpc-de-xiang-xi-bi-jiao/</link><pubDate>Wed, 04 Sep 2024 02:40:44 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-09-04-rest-yu-grpc-de-xiang-xi-bi-jiao/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-04-rest-yu-grpc-de-xiang-xi-bi-jiao/cover.jpg" alt="Featured image of post REST 与 gRPC 的详细比较" /&gt;&lt;p&gt;在很长一段时间里，REST 是构建 API 的唯一“标准”。它在某种程度上取代了 SOAP，后者因为“太多的 XML”而变得混乱不堪。&lt;/p&gt;
&lt;p&gt;但近年来，新的选择出现了。2015 年，Facebook 向公众发布了 GraphQL，2016 年，谷歌紧随其后，发布了 gRPC。在这篇文章中，我们将重点关注后者，并将其与仍然广泛使用的 REST 进行比较。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-04-rest-yu-grpc-de-xiang-xi-bi-jiao/001-45a56366.jpg"&gt;&lt;/p&gt;
&lt;h2 id="概述"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h2&gt;&lt;p&gt;下表将为您提供讨论要点的概览，并展示了 REST 和 gRPC 真正闪耀的地方。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;主题&lt;/th&gt;
 &lt;th&gt;REST&lt;/th&gt;
 &lt;th&gt;gRPC&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;标准化&lt;/td&gt;
 &lt;td&gt;无标准&lt;/td&gt;
 &lt;td&gt;定义明确&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;范式&lt;/td&gt;
 &lt;td&gt;基于资源&lt;/td&gt;
 &lt;td&gt;RPC&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;服务模式&lt;/td&gt;
 &lt;td&gt;仅单向&lt;/td&gt;
 &lt;td&gt;单向、客户端流、服务器流和双向流&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;要求&lt;/td&gt;
 &lt;td&gt;任何 HTTP 版本，JSON 解析器&lt;/td&gt;
 &lt;td&gt;HTTP/2，gRPC 语言实现&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;API 设计&lt;/td&gt;
 &lt;td&gt;代码优先&lt;/td&gt;
 &lt;td&gt;设计优先&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;默认数据格式&lt;/td&gt;
 &lt;td&gt;JSON&lt;/td&gt;
 &lt;td&gt;Protobuf&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;浏览器支持&lt;/td&gt;
 &lt;td&gt;原生&lt;/td&gt;
 &lt;td&gt;gRPC Web，通过变通方法&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;工具&lt;/td&gt;
 &lt;td&gt;更成熟的工具&lt;/td&gt;
 &lt;td&gt;语言支持各异，部分有出色的实现&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="标准化"&gt;&lt;a href="#%e6%a0%87%e5%87%86%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;标准化
&lt;/h2&gt;&lt;p&gt;REST 的一个缺点是缺乏标准化。REST 更像是一种范式，而不是 API 标准，许多人对它的理解各不相同。对大多数人来说，“REST API”一词用于指代基于 HTTP 的 JSON API。对其他人来说，REST 可以与某些规范如 HATEOAS 或 JSON:API 互换使用。但即使使用 XML 而不是 JSON，API 仍然可以是 RESTful 的，尽管这一点并不广为人知。REST 这个术语甚至不与 HTTP 绑定。这在处理 REST API 时可能导致很多混淆。例如，消费者可能会自动期望某些 REST API 端点具有幂等性或可缓存性，尽管这些并没有明确定义。&lt;/p&gt;
&lt;p&gt;相比之下，gRPC 定义明确。例如，gRPC 在 HTTP/2 上的实现非常详细。&lt;/p&gt;
&lt;h2 id="根本差异"&gt;&lt;a href="#%e6%a0%b9%e6%9c%ac%e5%b7%ae%e5%bc%82" class="header-anchor"&gt;&lt;/a&gt;根本差异
&lt;/h2&gt;&lt;p&gt;REST 和 gRPC 的范式不同。&lt;/p&gt;
&lt;p&gt;在 REST 中，一切都围绕资源展开，资源可以被检索和操作。如果我们以书籍为例，REST API 通常会提供以下端点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /books&lt;/code&gt;（获取所有书籍，很可能带有用于过滤和分页结果的参数）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /books/{id}&lt;/code&gt;（获取特定书籍）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /books&lt;/code&gt;（创建书籍）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /books/{id}&lt;/code&gt;（删除书籍）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大多数基于 HTTP 的 REST API 都遵循这种模式。虽然这种方式运作良好，但在某些情况下，作为 REST API 表示起来比较困难。例如，如果我想一次性创建多本书籍，而不想为每本书重复调用&lt;code&gt;POST /books&lt;/code&gt;（出于性能、幂等性或其他原因），我该怎么办？我创建一个&lt;code&gt;POST /books/batch&lt;/code&gt;端点吗？这还是“RESTful”的吗？虽然技术上容易解决，但它经常在开发者之间引发长时间的讨论。&lt;/p&gt;
&lt;p&gt;另一方面，gRPC 是一个 RPC 框架。它围绕服务方法展开。如果我们以书籍 API 为例，使用 gRPC，我们会创建一个&lt;code&gt;BookService&lt;/code&gt;，包含以下方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GetBooks()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetBook()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CreateBook()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DeleteBook()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们可以随意命名这些方法，并需要任何我们需要的参数。如果我们现在想添加一个创建多本书籍的方法，没有什么可以阻止我们添加一个&lt;code&gt;CreateBooks()&lt;/code&gt;方法。gRPC 在设计 API 时提供了更多的“自由”，因为（自我施加的）限制更少。&lt;/p&gt;
&lt;h3 id="服务模式"&gt;&lt;a href="#%e6%9c%8d%e5%8a%a1%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;服务模式
&lt;/h3&gt;&lt;p&gt;gRPC 支持四种服务方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;单向：&lt;/strong&gt; 发送单个请求，接收单个响应&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务器流：&lt;/strong&gt; 发送单个请求，接收多个响应&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;客户端流：&lt;/strong&gt; 发送多个请求，接收单个响应&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;双向流：&lt;/strong&gt; 发送多个请求，接收多个响应&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;与仅支持单向请求的 REST 相比，这是 gRPC 的一个非常大的优势。在 REST API 中支持其他服务模式将需要使用不同的协议，如服务器发送事件或 WebSockets，这并不完全是“RESTful”的。&lt;/p&gt;
&lt;h3 id="要求"&gt;&lt;a href="#%e8%a6%81%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;要求
&lt;/h3&gt;&lt;p&gt;REST API 通常“只要工作”就可以与任何类型的 HTTP 版本一起使用。只要编程语言具有 HTTP 客户端和 JSON 解析库，消费 REST API 就变得轻而易举。&lt;/p&gt;
&lt;p&gt;gRPC 明确需要 HTTP/2 支持，否则它将无法工作。近年来，这已不再是一个问题，因为大多数代理和框架都增加了对 HTTP/2 的支持。&lt;/p&gt;
&lt;p&gt;由于 gRPC 需要代码生成（用于创建客户端或服务器存根），因此只支持一组编程语言。&lt;/p&gt;
&lt;h2 id="api-设计"&gt;&lt;a href="#api-%e8%ae%be%e8%ae%a1" class="header-anchor"&gt;&lt;/a&gt;API 设计
&lt;/h2&gt;&lt;p&gt;REST API 通常是其实现的结果，被称为“代码优先”。虽然可以先设计 OpenAPI，然后生成服务器存根，但这不是许多开发者采取的方法。OpenAPI 定义更有可能从 API 实现中生成，如果有 OpenAPI 定义的话。因此，API 定义与实现紧密耦合。错误的模型/类的更改可能导致 API 的意外破坏性更改。&lt;/p&gt;
&lt;p&gt;gRPC 采用不同的方法，其中 API 必须在实现之前定义（被称为“设计优先”）。然后从这个 API 定义生成客户端和服务器存根。这需要一些预先思考，因为不能直接跳入实现 API。&lt;/p&gt;
&lt;p&gt;两种方法都有其优缺点。通常的 REST API 方法允许更快的迭代，因为服务器始终是真实的来源。使用 gRPC，可能很烦人，必须首先更改 API 定义，然后才能调整实现。然而，它通过明确定义 API 带来了一些安全优势。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-09-04-rest-yu-grpc-de-xiang-xi-bi-jiao/002-c4430419.jpg"&gt;&lt;/p&gt;
&lt;h2 id="数据格式"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;数据格式
&lt;/h2&gt;&lt;p&gt;REST 和 gRPC 都可以使用不同的格式传输数据。大多数 REST API 使用 JSON，而 gRPC 默认使用 Protocol Buffers（Protobuf），因此我们将比较这两种。&lt;/p&gt;
&lt;p&gt;JSON 对数据类型的支持有限，也有一些怪癖（例如，大数字需要作为字符串表示）。它是一种文本格式，人类可读。字段名被序列化，这占用了一些空间。在某些编程语言中，这也需要使用反射来反序列化 JSON 消息，这相当慢。&lt;/p&gt;
&lt;p&gt;如上所述，gRPC API 及其相应的消息类型首先被定义为 Protocol Buffers。每个消息都是强类型的，可能包含有用的注释，并且有许多其他有趣的特性。对于支持的编程语言列表，可以自动生成（反）序列化消息的代码。由于它是一种二进制格式，并且不序列化字段名，它比等效的 JSON 消息占用的空间更少。这确实有一个缺点，即它不再是人类可读的，需要 Protobuf 定义来反序列化消息，这可能会妨碍开发体验。&lt;/p&gt;
&lt;p&gt;以下 JSON 示例大约占用 66 字节（去除空格）。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{ &amp;quot;persons&amp;quot;: [ { &amp;quot;name&amp;quot;: &amp;quot;Max&amp;quot;, &amp;quot;age&amp;quot;: 23 }, { &amp;quot;name&amp;quot;: &amp;quot;Mike&amp;quot;, &amp;quot;age&amp;quot;: 52 } ] } &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;等效的序列化 protobuf 消息只会使用 19 字节。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0x0A070A034D617810170A080A0448616E731034 &lt;/code&gt;&lt;/p&gt;
&lt;h3 id="大消息"&gt;&lt;a href="#%e5%a4%a7%e6%b6%88%e6%81%af" class="header-anchor"&gt;&lt;/a&gt;大消息
&lt;/h3&gt;&lt;p&gt;Protobuf 旨在在内存中序列化和反序列化消息。因此，不建议使用 Protobuf/gRPC 传输大消息。大多数 gRPC 实现对单个消息设置了默认的 4MB 限制。&lt;/p&gt;
&lt;p&gt;使用 REST API 处理大数据大小（如文件上传）相对直接。接收到的文件可以作为流处理，使用很少的内存。这在 gRPC 中并非不可能，但需要更多的手动努力。文件需要在发送方分成几个部分。然后每个部分作为单独的消息通过客户端流方法发送到服务器。服务器接收每个部分，并可以从中构建数据流，从而实现与 REST API 类似的行为，尽管需要更多的努力。&lt;/p&gt;
&lt;h2 id="浏览器兼容性"&gt;&lt;a href="#%e6%b5%8f%e8%a7%88%e5%99%a8%e5%85%bc%e5%ae%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;浏览器兼容性
&lt;/h2&gt;&lt;p&gt;这是 REST 真正闪耀的地方。它被 Web 浏览器原生支持，使得从 Web 应用程序消费 REST API 变得毫不费力。&lt;/p&gt;
&lt;p&gt;gRPC 并不直接被浏览器支持，因为它需要明确的 HTTP/2 支持和访问某些 HTTP/2 特性，而 Web 浏览器并不提供。作为变通方法，可以使用 gRPC Web。它是 gRPC 协议的轻微变体，使其可以被 Web 浏览器消费。对于某些编程语言，gRPC Web 支持已经包含在框架中。对于其他语言，需要一个代理来将 gRPC 流量转换为 gRPC Web 流量，反之亦然。与不需要依赖的 REST API 相比，从 Web 消费 gRPC API 更加繁琐。&lt;/p&gt;
&lt;p&gt;一个变通方法是使用 JSON 转码，它允许开发人员将 gRPC API 作为 REST API 公开。&lt;/p&gt;
&lt;p&gt;gRPC 和 REST 工具在编程语言和框架之间的差异很大。在某些情况下，gRPC 感觉更“原生”，而在其他情况下，REST 工具更加先进。&lt;/p&gt;
&lt;p&gt;适当的 gRPC 语言支持非常重要，因为它需要工具来生成客户端和服务器存根。对于不支持的编程语言，你将无计可施。REST API 的客户端总是可以手动创建的，但这可能需要一些努力。虽然存在从 OpenAPI 定义创建 REST 客户端的工具，但与 gRPC 等效工具相比，它们的开发体验通常较差。&lt;/p&gt;
&lt;p&gt;由于 REST API 已经存在了很长时间，因此存在更多帮助构建、测试和部署 REST API 的工具。它们的功能通常比 gRPC 工具更先进。&lt;/p&gt;
&lt;h2 id="结论"&gt;&lt;a href="#%e7%bb%93%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;结论
&lt;/h2&gt;&lt;p&gt;REST 和 gRPC 都有其优点和缺点。&lt;/p&gt;
&lt;p&gt;从 Web 应用程序消费 REST API 通常更容易。 REST 也更广泛地被使用，对于某些开发者来说，可能更简单，因为他们可能不了解 gRPC。&lt;/p&gt;
&lt;p&gt;在我看来，gRPC 在服务器到服务器通信（例如，微服务之间）中肯定有优势。 能够共享确切的 API 定义，并在多种编程语言中创建 API 客户端是一个巨大的胜利。&lt;/p&gt;</description></item><item><title>Java 和 JVM 自 JDK 8 至 21 的特性概览</title><link>https://xiaobox.github.io/p/2024-03-15-java-he-jvm-zi-jdk-8-zhi-21-de-te-xing-gai-lan/</link><pubDate>Fri, 15 Mar 2024 16:48:40 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-03-15-java-he-jvm-zi-jdk-8-zhi-21-de-te-xing-gai-lan/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-03-15-java-he-jvm-zi-jdk-8-zhi-21-de-te-xing-gai-lan/cover.jpg" alt="Featured image of post Java 和 JVM 自 JDK 8 至 21 的特性概览" /&gt;&lt;h2 id="引言"&gt;&lt;a href="#%e5%bc%95%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;引言
&lt;/h2&gt;&lt;p&gt;Java，这门自 1995 年诞生以来就广受欢迎的编程语言，以其跨平台的特性、强大的生态系统和稳定的性能表现，成为了软件开发领域的一个重要里程碑。随着时间的推移，Java 不断演进，以适应新的技术挑战和市场需求。自 JDK 8 发布以来，Java 平台经历了一系列重大的更新，每一次更新都为开发者带来了新的工具和能力，以构建更加高效、安全和现代化的应用程序。&lt;/p&gt;
&lt;h3 id="java-的历史和发展"&gt;&lt;a href="#java-%e7%9a%84%e5%8e%86%e5%8f%b2%e5%92%8c%e5%8f%91%e5%b1%95" class="header-anchor"&gt;&lt;/a&gt;Java 的历史和发展
&lt;/h3&gt;&lt;p&gt;从最初的 Java 1.0 到现在的 JDK 21，Java 语言和其运行环境 JVM（Java 虚拟机）已经走过了一段漫长的道路。Java 1.0 引入了最基本的面向对象编程概念，而随后的版本则不断扩展其功能，包括引入了泛型、注解、枚举类型等。JDK 5 和 JDK 8 是两个特别重要的版本，它们分别引入了自动装箱/拆箱和 Lambda 表达式，极大地简化了 Java 代码的编写。&lt;/p&gt;
&lt;h3 id="jdk-8-至-21-的重要性"&gt;&lt;a href="#jdk-8-%e8%87%b3-21-%e7%9a%84%e9%87%8d%e8%a6%81%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;JDK 8 至 21 的重要性
&lt;/h3&gt;&lt;p&gt;JDK 8 是一个转折点，它标志着 Java 进入了一个新的时代。这个版本引入了函数式编程的特性，使得 Java 开发者能够以更加声明式的方式编写并发和事件驱动的代码。随后的版本，如 JDK 11、JDK 14 和 JDK 16，都在不断地扩展和深化这些特性，同时引入了许多其他的改进，如模块系统、记录类和模式匹配等。JDK 21 继续这一趋势，带来了更多的语言和 API 改进，以及对 JVM 的优化。&lt;/p&gt;
&lt;h3 id="本文的目的和结构"&gt;&lt;a href="#%e6%9c%ac%e6%96%87%e7%9a%84%e7%9b%ae%e7%9a%84%e5%92%8c%e7%bb%93%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;本文的目的和结构
&lt;/h3&gt;&lt;p&gt;本文旨在为 Java 开发者提供一个全面的概览，介绍自 JDK 8 至 JDK 21 期间引入的所有重要特性。我们将按照特性的类型和用途进行分类，包括新语言特性、新 APIs、性能改进、安全增强、启动和打包工具的更新、Javadoc 和字节码的变更，以及新支持的平台和版本方案。此外，我们还将讨论那些已被弃用或移除的特性，以及这些变化对 Java 生态系统的长期影响。&lt;/p&gt;
&lt;p&gt;通过本文，您将能够获得对 Java 最新特性的深入理解，无论您是 Java 新手还是经验丰富的开发者，都能从中获得宝贵的知识和见解。接下来，让我们开始探索 Java 自 JDK 8 以来的演变之旅。&lt;/p&gt;
&lt;h2 id="新语言特性详细解析"&gt;&lt;a href="#%e6%96%b0%e8%af%ad%e8%a8%80%e7%89%b9%e6%80%a7%e8%af%a6%e7%bb%86%e8%a7%a3%e6%9e%90" class="header-anchor"&gt;&lt;/a&gt;新语言特性详细解析
&lt;/h2&gt;&lt;h3 id="模式匹配pattern-matching"&gt;&lt;a href="#%e6%a8%a1%e5%bc%8f%e5%8c%b9%e9%85%8dpattern-matching" class="header-anchor"&gt;&lt;/a&gt;模式匹配（Pattern Matching）
&lt;/h3&gt;&lt;p&gt;模式匹配是 Java 语言中一项革命性的新特性，它首次作为预览特性在 JDK 12 中引入，并在 JDK 16 中正式成为 Java 语言的一部分。这一特性借鉴了函数式编程语言中的模式匹配概念，允许开发者以一种更加简洁和表达性强的方式来检查和处理不同类型的数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模式匹配的引入背景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在模式匹配出现之前，Java 开发者通常使用&lt;code&gt;if-else&lt;/code&gt;语句或者&lt;code&gt;instanceof&lt;/code&gt;检查来处理不同类型的对象，这不仅使得代码变得冗长，而且可读性也较差。模式匹配的引入，为 Java 提供了一种新的、更加直观的方式来处理这些情况，特别是在处理复杂的对象结构时，它能够显著提高代码的清晰度和维护性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模式匹配的具体用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;模式匹配在 Java 中的实现主要通过&lt;code&gt;instanceof&lt;/code&gt;和&lt;code&gt;switch&lt;/code&gt;表达式来完成。下面是一个使用模式匹配的简单例子：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getSomeObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;instanceof&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 在这里可以直接使用变量 s，无需进行显式的类型转换&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;String length is &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;instanceof&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 对于整型对象 i，可以直接进行数学运算&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Integer value is &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Unknown object type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在上面的代码中，&lt;code&gt;instanceof&lt;/code&gt;关键字后面紧跟着的是一个模式变量&lt;code&gt;s&lt;/code&gt;或&lt;code&gt;i&lt;/code&gt;，当&lt;code&gt;obj&lt;/code&gt;的类型与模式匹配时，变量会被自动赋值，无需显式的类型转换。这种写法不仅简化了代码，还减少了出错的可能性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模式匹配的优势和实例分析&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;模式匹配的优势在于它的简洁性和表达性。它允许开发者用更少的代码来表达更复杂的意思，并且使得代码的意图更加明确。此外，模式匹配还支持更复杂的结构，如嵌套的模式和守卫条件，这在处理复杂的数据结构时非常有用。&lt;/p&gt;
&lt;p&gt;让我们来看一个更复杂的例子，其中使用了守卫条件和嵌套模式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getNumbers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;absNumber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Unsupported number type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;absNumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们使用了一个&lt;code&gt;switch&lt;/code&gt;表达式来进行模式匹配。对于每种情况，我们都定义了一个模式，并在需要时使用守卫条件来进一步细化匹配的规则。这样，我们就能够根据不同的输入执行不同的操作，并且代码的结构依然保持清晰和简洁。&lt;/p&gt;
&lt;p&gt;总的来说，模式匹配为 Java 带来了一种新的、强大的数据处理方式，它不仅提高了代码的可读性和可维护性，而且还使得 Java 语言更加现代化，更接近于其他流行的函数式编程语言。随着 Java 语言的不断发展，我们可以期待模式匹配在未来的 Java 版本中将发挥更加重要的作用。&lt;/p&gt;
&lt;h3 id="未命名变量和未命名模式"&gt;&lt;a href="#%e6%9c%aa%e5%91%bd%e5%90%8d%e5%8f%98%e9%87%8f%e5%92%8c%e6%9c%aa%e5%91%bd%e5%90%8d%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;未命名变量和未命名模式
&lt;/h3&gt;&lt;p&gt;在 Java 14 中，作为预览特性引入的未命名变量（也称为“var”类型）和未命名模式（也称为“模式变量”），为 Java 编程带来了新的表达性和灵活性。这些特性旨在简化代码，特别是在处理复杂的数据结构和流操作时，它们允许开发者忽略不需要的值，并提供了一种新的数据解构方式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;未命名变量的概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未命名变量是 Java 中一种新的局部变量声明方式，它允许开发者声明一个变量而不需要预先指定其类型。这种变量的类型将由编译器根据赋值表达式自动推断。未命名变量通常与&lt;code&gt;-&amp;gt;&lt;/code&gt;操作符一起使用，后者在&lt;code&gt;switch&lt;/code&gt;表达式中用于提供更复杂的逻辑分支。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;未命名变量的使用场景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未命名变量特别适用于以下场景：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当你只关心一个表达式的结果，而不打算在后续代码中使用变量时。&lt;/li&gt;
&lt;li&gt;当你需要从方法返回值中提取信息，但又不想显式声明所有组成部分时。&lt;/li&gt;
&lt;li&gt;在流操作中，当你需要处理流中的元素，但不需要存储任何中间变量时。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;未命名模式的概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未命名模式是模式匹配的一个扩展，它允许开发者在&lt;code&gt;instanceof&lt;/code&gt;、&lt;code&gt;case&lt;/code&gt;标签或&lt;code&gt;catch&lt;/code&gt;块中声明一个模式变量，而不是一个具名变量。这在使用模式匹配解构复杂类型时非常有用，尤其是当你只需要访问类型的一部分数据时。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;未命名模式的使用场景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;未命名模式特别适用于以下场景：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当你使用模式匹配来检查对象的类型，但不需要访问对象的具体实例时。&lt;/li&gt;
&lt;li&gt;在解构复杂对象时，当你只需要对象的某些部分，而不是整个对象时。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;代码示例和实际应用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下面是一个使用未命名变量和未命名模式的示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 使用未命名变量处理 Optional&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;optStr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;optStr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 输出 &amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 使用未命名变量在 try-catch 中忽略不需要的异常&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 可能会抛出 CheckedException 的代码&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 忽略异常，不进行处理&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 使用未命名模式在 switch 表达式中解构对象&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 只关心 x 的值，y 的值被忽略&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;X coordinate is &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在上述代码中，我们看到了未命名变量和未命名模式如何在不同场景下简化代码。未命名变量使得我们可以避免声明不必要的变量，而未命名模式则让我们能够更加灵活地处理复杂的数据结构。&lt;/p&gt;
&lt;p&gt;总的来说，未命名变量和未命名模式是 Java 语言中两项非常有用的新特性，它们通过减少代码冗余和提高表达性，使得 Java 代码更加简洁和易于理解。随着这些特性在未来的 Java 版本中逐渐成熟和稳定，我们可以预见它们将在 Java 编程实践中发挥越来越重要的作用。&lt;/p&gt;
&lt;h3 id="封闭类和记录类"&gt;&lt;a href="#%e5%b0%81%e9%97%ad%e7%b1%bb%e5%92%8c%e8%ae%b0%e5%bd%95%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;封闭类和记录类
&lt;/h3&gt;&lt;p&gt;随着 Java 语言不断发展，为了更好地支持函数式编程和数据建模，JDK 16 引入了两种新的类类型：封闭类（Sealed Classes）和记录类（Record Classes）。这些新特性旨在提供更丰富的类型安全保障和更简洁的代码表达，特别是在创建数据传输对象（DTOs）和限制继承结构时。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封闭类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;封闭类是一种特殊的类，它限制了哪些其他类可以继承它。这一特性对于那些希望限制子类数量或者想要精确控制继承树的开发者来说非常有用。在 Java 中，封闭类通过&lt;code&gt;sealed&lt;/code&gt;关键字进行声明，并且可以指定一个允许的子类列表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封闭类的概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;封闭类的概念是为了在 Java 中引入更多的类型安全性和清晰性。它们允许开发者定义一个基类，同时限制哪些类可以扩展这个基类。这样做的好处是可以防止其他开发者创建不必要的或者不安全的子类，从而保护 API 的稳定性和可预测性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封闭类的使用场景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;封闭类适用于以下场景：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当你想要创建一个基类，但只想允许特定的子类时。&lt;/li&gt;
&lt;li&gt;当你想要限制类的继承结构，以避免类的滥用或错误扩展时。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;封闭类示例&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;abstract&lt;/span&gt; &lt;span class="n"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="ne"&gt;Shape&lt;/span&gt; &lt;span class="n"&gt;permits&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Triangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;封闭类的基类代码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="ne"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;圆形的具体实现&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Rectangle&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="ne"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;矩形的具体实现&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;以下代码将无法编译，因为&lt;/span&gt; &lt;span class="n"&gt;Square&lt;/span&gt; &lt;span class="err"&gt;没有在&lt;/span&gt; &lt;span class="ne"&gt;Shape&lt;/span&gt; &lt;span class="err"&gt;的&lt;/span&gt; &lt;span class="n"&gt;permits&lt;/span&gt; &lt;span class="err"&gt;子句中声明&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Square&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="ne"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;正方形的具体实现&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，&lt;code&gt;Shape&lt;/code&gt;是一个封闭类，它明确指定了哪些类可以作为其子类。这确保了&lt;code&gt;Shape&lt;/code&gt;的继承结构是受控的，并且防止了任何未授权的扩展。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;记录类&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;记录类是一种特殊的类，它主要用于创建不可变的数据传输对象（DTOs）。记录类的语法比传统的类更加简洁，它自动为所有字段生成构造函数、&lt;code&gt;equals&lt;/code&gt;、&lt;code&gt;hashCode&lt;/code&gt;和&lt;code&gt;toString&lt;/code&gt;方法。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;记录类的概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;记录类的概念是为了简化 Java 中不可变数据结构的创建。它们提供了一种快速定义类的方式，而无需编写大量的样板代码。记录类是不可变的，这意味着一旦创建，其状态就不能改变，这有助于避免并发问题和不必要的错误。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;记录类的使用场景&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;记录类适用于以下场景：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;当你需要创建一个简单的数据结构，用于存储一组固定的值时。&lt;/li&gt;
&lt;li&gt;当你希望确保数据的不可变性，以提高代码的安全性和可维护性时。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;记录类示例&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 输出 &amp;#34;Point[x=10, y=20]&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们定义了一个名为&lt;code&gt;Point&lt;/code&gt;的记录类，它有两个字段：&lt;code&gt;x&lt;/code&gt;和&lt;code&gt;y&lt;/code&gt;。创建记录类时，Java 自动为我们生成了构造函数和&lt;code&gt;toString&lt;/code&gt;方法，使得代码非常简洁。此外，由于记录类是不可变的，我们可以安全地在多线程环境中共享&lt;code&gt;Point&lt;/code&gt;实例，而不必担心它们的内部状态会被改变。&lt;/p&gt;
&lt;p&gt;总的来说，封闭类和记录类为 Java 开发者提供了更多的选择，以适应不同的编程场景。封闭类通过限制继承结构来增强类型安全性，而记录类则通过简化数据结构的创建来提高开发效率。这些新特性的引入，进一步丰富了 Java 语言的功能，使其更加现代化和高效。随着这些特性在未来的 Java 版本中得到进一步的发展和完善，我们有理由相信它们将成为 Java 编程中不可或缺的一部分。&lt;/p&gt;
&lt;h3 id="其他重要语言特性"&gt;&lt;a href="#%e5%85%b6%e4%bb%96%e9%87%8d%e8%a6%81%e8%af%ad%e8%a8%80%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;其他重要语言特性
&lt;/h3&gt;&lt;p&gt;除了前面提到的模式匹配、未命名变量和未命名模式等特性，Java 在 JDK 8 至 21 的版本中还引入了许多其他重要的语言特性。这些特性涵盖了从代码简化到性能优化的各个方面，极大地提升了 Java 编程的便捷性和表达能力。接下来，我们将详细探讨其中的一些关键特性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;String 模板&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 16 引入了字符串模板（String Templates），这是一种新的字符串字面量，它允许开发者以一种更加简洁和安全的方式来创建格式化的字符串。字符串模板通过&lt;code&gt;str&lt;/code&gt;前缀定义，并支持多行字符串和插值表达式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符串模板的用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;字符串模板提供了一种新的字符串创建方式，它结合了字符串字面量的简洁性和&lt;code&gt;String.format&lt;/code&gt;方法的格式化能力。开发者可以在模板中直接插入变量和表达式，而不需要额外的格式化步骤。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;World&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 使用字符串模板创建格式化的字符串&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 输出 &amp;#34;Hello, World! The value is 84.&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们使用&lt;code&gt;${}&lt;/code&gt;来插入变量和表达式的值，这使得字符串的创建和格式化过程变得更加直观和方便。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;字符串模板的优势&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;字符串模板的主要优势在于它的简洁性和易读性。它减少了字符串拼接和格式化的复杂性，使得代码更加清晰和易于维护。此外，由于字符串模板是编译时常量，它们在某些情况下还能提供更好的性能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文本块&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;文本块（Text Blocks）是 Java 13 中引入的预览特性，它允许开发者以多行字符串的形式编写代码，而无需使用传统的转义序列。文本块通过三个双引号（&lt;code&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/code&gt;）定义，并且保持了字符串字面量的原始格式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文本块的用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;文本块特别适用于创建多行的字符串，例如在编写正则表达式、HTML 模板或 SQL 查询时。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;h1&amp;gt;Title&amp;lt;/h1&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;p&amp;gt;Paragraph with line breaks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; and multiple lines.&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们定义了一个包含 HTML 内容的文本块，所有的换行符和空格都被保留，而不需要使用传统的&lt;code&gt;\n&lt;/code&gt;转义序列。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文本块的优势&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;文本块的主要优势在于它们的易读性和编写效率。它们使得多行字符串的创建变得非常简单，同时避免了转义序列带来的混乱和错误。此外，文本块还支持跨多行的字符串连接，进一步提高了代码的灵活性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Helpful NullPointerExceptions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 14 中引入了更加有用的&lt;code&gt;NullPointerException&lt;/code&gt;，它提供了关于哪个变量为&lt;code&gt;null&lt;/code&gt;的详细信息。这一特性通过&lt;code&gt;-XX:+ShowCodeDetailsInExceptionMessages&lt;/code&gt; JVM 选项启用，它使得空指针异常更加易于调试。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Helpful NullPointerExceptions 的用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当程序抛出&lt;code&gt;NullPointerException&lt;/code&gt;时，JVM 会提供更多的堆栈跟踪信息，包括导致异常的变量名和代码位置。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;String message = null;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;int length = message.length(); // 这里会抛出 NullPointerException
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，如果启用了详细异常信息，我们将会得到类似于以下的输出：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Exception in thread &amp;#34;main&amp;#34; java.lang.NullPointerException:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; Cannot read field &amp;#34;length&amp;#34; because &amp;#34;message&amp;#34; is null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; at com.example.Main.main(Main.java:10)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Helpful NullPointerExceptions 的优势&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这一特性的主要优势在于它提供了更多的调试信息，使得开发者能够快速定位和修复空指针异常。这种增强的异常信息极大地提高了 Java 程序的可维护性和稳定性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Switch 表达式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Switch 表达式是 Java 12 中引入的预览特性，它为&lt;code&gt;switch&lt;/code&gt;语句提供了一种更加简洁和灵活的替代方案。Switch 表达式使用&lt;code&gt;yield&lt;/code&gt;关键字返回值，并且可以与模式匹配结合使用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Switch 表达式的用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Switch 表达式可以替代传统的&lt;code&gt;switch&lt;/code&gt;语句，特别是在处理枚举类型和表达式时。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MONDAY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;numLetters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MONDAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FRIDAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SUNDAY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TUESDAY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;yield&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numLetters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 输出 &amp;#34;5&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们使用了一个&lt;code&gt;switch&lt;/code&gt;表达式来根据&lt;code&gt;day&lt;/code&gt;的值计算字母的数量。与传统的&lt;code&gt;switch&lt;/code&gt;语句相比，Switch 表达式提供了一种更加简洁和函数式的方法来处理条件逻辑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Switch 表达式的优势&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Switch 表达式的主要优势在于它的简洁性和表达性。它减少了模板代码的数量，并且使得条件逻辑的编写更加直观和易于理解。此外，Switch 表达式还支持与模式匹配的结合使用，进一步提高了代码的灵活性和可读性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 语言在 JDK 8 至 21 的版本中引入了许多重要的新特性，这些特性不仅提高了代码的编写效率，还增强了程序的性能和安全性。从字符串模板和文本块的引入，到 Helpful NullPointerExceptions 和 Switch 表达式的改进，Java 不断地在进化，以满足现代软件开发的需求。随着这些特性在未来的 Java 版本中得到进一步的发展和完善，我们有理由相信它们将成为 Java 编程中不可或缺的一部分。&lt;/p&gt;
&lt;h2 id="新-apis-的探索"&gt;&lt;a href="#%e6%96%b0-apis-%e7%9a%84%e6%8e%a2%e7%b4%a2" class="header-anchor"&gt;&lt;/a&gt;新 APIs 的探索
&lt;/h2&gt;&lt;p&gt;Java 平台的不断更新带来了丰富的新 APIs，这些 APIs 旨在提高开发者的生产力，简化复杂任务的处理，并增强 Java 在各个领域的应用能力。从集合操作的增强到数学函数的扩展，新 APIs 为 Java 开发者提供了更多的工具来构建高效、健壮的应用程序。&lt;/p&gt;
&lt;h3 id="集合和数学函数-api"&gt;&lt;a href="#%e9%9b%86%e5%90%88%e5%92%8c%e6%95%b0%e5%ad%a6%e5%87%bd%e6%95%b0-api" class="header-anchor"&gt;&lt;/a&gt;集合和数学函数 API
&lt;/h3&gt;&lt;p&gt;集合 API 是 Java 中使用最广泛的 API 之一，它提供了一系列的数据结构和算法来存储和操作对象集合。数学函数 API 则为数值计算提供了支持，包括随机数生成、复数操作等。在 JDK 8 至 21 的更新中，这两个领域的 API 得到了显著的扩展和改进。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新增集合 API 的特性和用法&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 JDK 8 中引入的 Stream API 彻底改变了 Java 中集合的处理方式，而在后续的版本中，这一 API 继续得到了增强。例如，JDK 16 引入了&lt;code&gt;toList()&lt;/code&gt;方法，它简化了从 Stream 到 List 的转换过程，使得开发者可以更方便地进行数据收集。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;List&amp;lt;String&amp;gt; list = Stream.of(&amp;#34;apple&amp;#34;, &amp;#34;banana&amp;#34;, &amp;#34;cherry&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; .collect(Collectors.toList());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;此外，JDK 16 还引入了&lt;code&gt;Map.of&lt;/code&gt;和&lt;code&gt;Set.of&lt;/code&gt;等静态工厂方法，它们用于创建不可变的 Map 和 Set 实例，这不仅提高了代码的可读性，还减少了创建空集合时的内存消耗。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数学函数 API 的增强&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 8 引入了&lt;code&gt;java.util.function&lt;/code&gt;包，其中包括了一系列的函数式接口，为 Java 带来了函数式编程的特性。在此基础上，后续的 Java 版本继续增强数学函数 API。例如，JDK 11 中引入了&lt;code&gt;Math.log10&lt;/code&gt;方法，用于计算一个数的以 10 为底的对数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;double result = Math.log10(100); // 结果为 2.0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;JDK 16 进一步扩展了数学函数库，包括对&lt;code&gt;BigDecimal&lt;/code&gt;的改进，使得大数运算更加精确和高效。此外，JDK 16 还引入了&lt;code&gt;Random&lt;/code&gt;和&lt;code&gt;ThreadLocalRandom&lt;/code&gt;的新的 APIs，提供了更多的随机数生成选项。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实际应用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新的集合和数学函数 API 在实际应用中极大地提高了开发效率。例如，在处理大量数据时，Stream API 的链式操作和新的集合工厂方法使得代码更加简洁和易于理解。在科学计算和金融分析领域，增强的数学函数 API 提供了更精确的数值计算能力，帮助开发者实现了更复杂的数学模型。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结论&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;集合和数学函数 API 的持续更新和改进，反映了 Java 平台对开发者需求的响应和对现代编程挑战的适应。这些新 APIs 不仅提高了 Java 语言的表达能力，还为解决复杂问题提供了更多的工具和选项。随着 Java 平台的不断发展，我们可以期待未来会有更多的创新和改进，进一步丰富 Java 生态系统。&lt;/p&gt;
&lt;h3 id="其他重要-api-更新"&gt;&lt;a href="#%e5%85%b6%e4%bb%96%e9%87%8d%e8%a6%81-api-%e6%9b%b4%e6%96%b0" class="header-anchor"&gt;&lt;/a&gt;其他重要 API 更新
&lt;/h3&gt;&lt;p&gt;随着 Java 平台的不断演进，除了集合和数学函数 API 之外，还有许多其他的 API 得到了更新和增强，以满足现代应用程序的需求。这些更新涵盖了文件和 IO 操作、网络编程、时间日期处理等多个方面，为 Java 开发者提供了更加强大和灵活的工具集。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文件和 IO 操作的改进&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 的文件和 IO 操作 API 在 JDK 8 至 21 期间经历了显著的改进。例如，JDK 11 引入了&lt;code&gt;Files.walk&lt;/code&gt;方法，它提供了一种更加简洁的方式来遍历文件树。此外，JDK 14 增加了&lt;code&gt;Files.mismatch&lt;/code&gt;方法，用于比较两个文件的内容差异，这对于文件校验和数据恢复等场景非常有用。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;startPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/path/to/start/directory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startPath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;isRegularFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;网络编程的新特性&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在网络编程方面，JDK 9 引入了&lt;code&gt;java.net.http.HttpClient&lt;/code&gt;，这是一个全新的、非阻塞的 HTTP 客户端 API，它提供了更加简洁和强大的 HTTP 请求处理能力。这个新的 HTTP 客户端支持 HTTP/2 协议，并且提供了 WebSocket 支持，使得 Java 在处理现代网络应用时更加高效。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;HttpClient client = HttpClient.newBuilder()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; .version(HttpClient.Version.HTTP_2)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; .build();
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;HttpRequest request = HttpRequest.newBuilder()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; .uri(URI.create(&amp;#34;https://example.com&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; .GET()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; .build();
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; .thenApply(HttpResponse::body)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; .thenAccept(System.out::println)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; .join();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;时间和日期 API 的更新&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 8 引入了&lt;code&gt;java.time&lt;/code&gt;包，这个包提供了一套全新的日期和时间 API，它解决了旧版&lt;code&gt;java.util.Date&lt;/code&gt;类中存在的问题，并提供了更好的时间日期处理能力。在后续的版本中，这个 API 继续得到了增强。例如，JDK 12 增加了&lt;code&gt;LocalDate&lt;/code&gt;的&lt;code&gt;ofEpochDay&lt;/code&gt;方法，它允许开发者直接从天数创建日期对象，而不需要通过&lt;code&gt;ChronoLocalDate&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;LocalDate date = LocalDate.ofEpochDay(10000); // 创建一个特定的日期
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;结论&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这些 API 的更新和增强不仅提高了 Java 语言的功能，还使得 Java 在处理文件操作、网络通信和时间日期处理等任务时更加高效和便捷。随着 Java 平台的不断发展，我们可以期待未来会有更多的创新和改进，进一步丰富 Java 生态系统，帮助开发者构建更加健壮和高效的应用程序。&lt;/p&gt;
&lt;h2 id="性能改进的深入分析"&gt;&lt;a href="#%e6%80%a7%e8%83%bd%e6%94%b9%e8%bf%9b%e7%9a%84%e6%b7%b1%e5%85%a5%e5%88%86%e6%9e%90" class="header-anchor"&gt;&lt;/a&gt;性能改进的深入分析
&lt;/h2&gt;&lt;p&gt;Java 平台的性能改进一直是开发者社区关注的焦点。从 JDK 8 至 21，Oracle 和 OpenJDK 社区持续致力于优化 Java 虚拟机（JVM）和 Java 语言的性能，以满足日益增长的应用程序性能需求。这些改进包括内存管理、垃圾回收、即时编译器（JIT）优化、启动时间缩短等方面。&lt;/p&gt;
&lt;h3 id="内存管理和垃圾回收"&gt;&lt;a href="#%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86%e5%92%8c%e5%9e%83%e5%9c%be%e5%9b%9e%e6%94%b6" class="header-anchor"&gt;&lt;/a&gt;内存管理和垃圾回收
&lt;/h3&gt;&lt;p&gt;内存管理和垃圾回收是 Java 性能改进中的关键领域。有效的内存管理确保了应用程序能够高效地使用内存资源，而垃圾回收机制则负责回收不再使用的对象，防止内存泄漏。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;弹性元空间&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 JDK 8 中，元空间（Metaspace）被引入作为&lt;code&gt;PermGen&lt;/code&gt;（永久代）的替代品，用于存储类的元数据。与&lt;code&gt;PermGen&lt;/code&gt;不同，元空间在本地内存中分配，理论上不受堆大小的限制。然而，随着应用程序规模的增长，元空间的内存使用也成为一个关注点。为了解决这一问题，JDK 16 引入了弹性元空间，它允许元空间的内存使用更加动态和可控，减少了对系统内存的占用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;G1 垃圾回收器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;G1（Garbage-First）垃圾回收器自 JDK 9 起成为默认的垃圾回收器。G1 是一种并行、增量、并发的垃圾回收器，旨在提供可预测的停顿时间模型，同时保持高吞吐量。G1 通过将堆划分为多个区域（Region）并跟踪每个区域的垃圾回收优先级来工作。它定期执行小型的回收任务，以减少应用程序的停顿时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ZGC 和 Shenandoah 垃圾回收器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ZGC（Z Garbage Collector）和 Shenandoah 垃圾回收器是两个实验性的垃圾回收器，它们在 JDK 11 及后续版本中作为实验特性提供。这两种回收器都旨在为大型堆（多达 4TB）提供低延迟的垃圾回收。ZGC 通过染色指针技术和并发标记周期来实现低延迟，而 Shenandoah 则通过并发标记和压缩来减少停顿时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NUMA-Aware 内存分配&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;随着多核处理器的普及，非一致性内存访问（NUMA）架构变得越来越常见。JDK 14 引入了 NUMA-Aware 内存分配，它允许 JVM 根据处理器的 NUMA 拓扑结构来优化内存分配，从而提高内存访问效率和整体性能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并行 Full GC 的改进&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JDK 10 中引入了并行 Full GC，它通过在 Full GC 过程中使用多个 GC 线程来提高垃圾回收的效率。这种改进显著减少了 Full GC 的停顿时间，特别是在处理大型堆或长时间运行的应用程序时。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;内存管理和垃圾回收的性能改进对于 Java 应用程序的稳定性和响应性至关重要。通过引入新的垃圾回收器、优化内存分配策略和提供更灵活的垃圾回收选项，Java 平台能够更好地适应不同类型和规模的应用程序。随着 Java 技术的不断发展，我们可以期待未来会有更多的内存管理和垃圾回收方面的创新，以满足日益增长的性能需求。&lt;/p&gt;
&lt;h3 id="jit-编译器和运行时性能"&gt;&lt;a href="#jit-%e7%bc%96%e8%af%91%e5%99%a8%e5%92%8c%e8%bf%90%e8%a1%8c%e6%97%b6%e6%80%a7%e8%83%bd" class="header-anchor"&gt;&lt;/a&gt;JIT 编译器和运行时性能
&lt;/h3&gt;&lt;p&gt;Java 虚拟机（JVM）中的即时编译器（JIT）是 Java 性能优化的关键组件。JIT 编译器负责将字节码动态编译为本地机器码，以提高执行效率。随着 JDK 版本的迭代，JIT 编译器也在不断进化，引入了新的优化技术和特性，以提升运行时性能和编译效率。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;JIT 编译器的优化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JIT 编译器的优化主要集中在减少编译时间和提高编译代码的质量上。这些优化包括更智能的编译触发策略、改进的热点检测算法、以及针对性能瓶颈的特定优化。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;分层编译&lt;/strong&gt;：JDK 11 引入了分层编译的概念，它允许 JVM 在不同的编译层次之间进行选择，以平衡编译时间和运行时性能。例如，JVM 可以使用快速的低层次编译器来编译不经常执行的代码，而将更高层次的优化编译器用于热点代码。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;编译器探测&lt;/strong&gt;：JDK 12 及后续版本中，编译器探测（也称为编译器引导）被引入，它允许 JVM 在运行时收集关于代码执行的更多信息，并使用这些信息来指导编译优化决策。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;代码缓存和重用&lt;/strong&gt;：JVM 通过缓存编译后的代码来避免重复编译相同的代码，这在处理具有多个版本的应用程序时尤其有用。此外，JVM 还可以在类加载器之间重用编译后的代码，减少了编译开销。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;运行时性能监控和诊断工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了帮助开发者更好地理解和优化 Java 应用程序的性能，JVM 提供了一系列的运行时监控和诊断工具。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Java Mission Control（JMC）&lt;/strong&gt;：JMC 是一个强大的性能分析工具，它可以收集和分析 JVM 的运行时信息，包括线程状态、内存使用情况和垃圾回收日志。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Flight Recorder&lt;/strong&gt;：Flight Recorder 是 JDK 11 中引入的一个轻量级事件记录框架，它可以在后台记录 JVM 的详细运行时事件，而对性能的影响非常小。开发者可以在需要时启动详细的事件记录，以进行性能分析。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JVM 统计信息 API&lt;/strong&gt;：JVM 统计信息 API（JVMS）提供了一组接口，允许应用程序查询 JVM 的运行时统计信息，如类加载次数、垃圾回收次数等。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;启动时间缩短&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;启动时间是 Java 应用程序性能的一个重要方面，特别是在需要快速响应的场景中。从 JDK 9 开始，Oracle 致力于减少 JVM 的启动时间，通过优化类加载和初始化过程，以及减少启动时的 JVM 内部处理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;应用类数据共享（Application Class-Data Sharing, ACDS）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ACDS 是 JDK 11 中引入的一个特性，它允许 JVM 在多个 Java 进程之间共享已编译的类数据。通过这种方式，JVM 可以减少启动时的编译工作量，从而缩短启动时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;快速应用启动（Fast Application Startup, FAS）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FAS 是 JDK 11 中的一个项目，旨在通过减少类元数据的加载和优化 JVM 的内存布局来加快应用启动速度。虽然 FAS 项目的一些目标在 JDK 11 中并未完全实现，但它为后续版本的启动时间优化奠定了基础。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JIT 编译器和运行时性能的优化是 Java 平台持续进步的重要组成部分。通过引入新的编译策略、监控工具和启动时间缩短技术，Java 能够为开发者提供更加高效和稳定的运行时环境。随着 Java 技术的不断发展，我们可以期待未来会有更多的性能优化特性，以满足日益增长的性能需求和挑战。&lt;/p&gt;
&lt;h2 id="安全改进的全面审视"&gt;&lt;a href="#%e5%ae%89%e5%85%a8%e6%94%b9%e8%bf%9b%e7%9a%84%e5%85%a8%e9%9d%a2%e5%ae%a1%e8%a7%86" class="header-anchor"&gt;&lt;/a&gt;安全改进的全面审视
&lt;/h2&gt;&lt;p&gt;Java 平台一直致力于提供安全可靠的编程环境，以保护用户和企业的数据安全。从 JDK 8 至 21，Java 的安全模型经历了一系列的改进，旨在提高安全性，防范新出现的威胁，并保持与现代安全标准和实践的一致性。&lt;/p&gt;
&lt;h3 id="加密和认证-api"&gt;&lt;a href="#%e5%8a%a0%e5%af%86%e5%92%8c%e8%ae%a4%e8%af%81-api" class="header-anchor"&gt;&lt;/a&gt;加密和认证 API
&lt;/h3&gt;&lt;p&gt;加密和认证 API 是 Java 安全体系中的重要组成部分，它们为 Java 应用程序提供了数据加密、解密、签名和验证等安全操作的能力。随着技术的发展，Java 对这些 API 进行了更新和增强，以支持新的加密算法和满足更高的安全标准。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新的加密算法和 API&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AES-GCM&lt;/strong&gt;：JDK 11 中引入了对 AES-GCM（Galois/Counter Mode）的支持，这是一种用于块加密算法的高效和安全的模式，特别适合处理网络通信中的数据加密和认证。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TLS 1.3&lt;/strong&gt;：Java 11 开始支持 TLS 1.3，这是传输层安全协议的最新版本，提供了更强大的加密算法、更少的握手轮次和更好的隐私保护。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SHA-3&lt;/strong&gt;：随着安全需求的不断演进，JDK 9 引入了对 SHA-3（Secure Hash Algorithm 3）的支持，这是新一代的哈希函数，旨在替代原有的 SHA-2。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;密钥管理和证书处理&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;密钥封装机制（KEM）API&lt;/strong&gt;：JDK 21 中引入了密钥封装机制（Key Encapsulation Mechanisms）API，它提供了一种封装和解封装密钥的方法，这对于密钥交换和密钥管理非常重要。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;证书透明度（Certificate Transparency, CT）&lt;/strong&gt;：Java 11 开始支持证书透明度 API，这是一种公开的、可审计的证书日志系统，用于监控和验证 SSL/TLS 证书的颁发。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;安全随机数生成器&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DRBG（Deterministic Random Bit Generator）&lt;/strong&gt;：Java 11 中引入了基于 NIST SP 800-90A 标准的确定性随机比特生成器（DRBG），它提供了可预测的、高质量的随机数，适用于安全敏感的应用场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;弃用和移除不安全的 API&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;不安全的加密算法&lt;/strong&gt;：随着安全意识的提高，Java 社区逐渐弃用了一些被认为是不安全的加密算法，如 DES 和 SHA-1，并推荐使用更安全的替代品。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;不安全的 SSL/TLS 协议&lt;/strong&gt;：Java 11 开始弃用 SSL 和早期版本的 TLS 协议，鼓励开发者使用 TLS 1.3 或更高版本，以确保通信的安全性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;加密和认证 API 的更新和增强是 Java 安全改进中的重要一环。通过引入新的加密算法、改进密钥管理和证书处理，以及提供更强大的随机数生成器，Java 平台能够更好地保护用户的数据安全和隐私。同时，通过弃用和移除不安全的 API，Java 鼓励开发者采用更加安全和现代的编程实践。随着 Java 技术的不断发展，我们可以期待未来会有更多的安全特性被引入，以应对不断变化的安全威胁和挑战。&lt;/p&gt;
&lt;h3 id="安全管理器和权限控制"&gt;&lt;a href="#%e5%ae%89%e5%85%a8%e7%ae%a1%e7%90%86%e5%99%a8%e5%92%8c%e6%9d%83%e9%99%90%e6%8e%a7%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;安全管理器和权限控制
&lt;/h3&gt;&lt;p&gt;在 Java 安全模型中，安全管理器（Security Manager）和权限控制（Access Control）扮演着至关重要的角色。它们确保了 Java 应用程序在一个受控的环境中运行，防止恶意代码访问敏感资源或执行危险操作。随着 Java 版本的更新，这些安全机制也在不断地得到加强和优化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安全管理器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;安全管理器是 Java 安全架构的核心组件，它负责执行安全策略，控制对系统资源的访问。通过安全管理器，Java 平台能够实施一系列的安全限制，如文件系统访问、网络连接和加密算法的使用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;策略文件和权限&lt;/strong&gt;：安全管理器通常与策略文件（如&lt;code&gt;java.security&lt;/code&gt;）一起工作，这些文件定义了代码可以请求的权限。开发者可以根据需要自定义策略文件，以放宽或限制特定的权限。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全管理器的配置&lt;/strong&gt;：在 JDK 9 中，安全管理器的配置方式发生了变化。&lt;code&gt;java.security&lt;/code&gt;文件不再位于 JRE 的&lt;code&gt;lib/security&lt;/code&gt;目录下，而是被&lt;code&gt;jdk.security&lt;/code&gt;文件所取代，这使得安全管理器的配置更加模块化和灵活。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;权限控制&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 的权限控制机制允许开发者精确地控制代码的访问权限。这些权限可以是文件系统访问、网络操作、安全属性修改等。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;java.security.Permissions&lt;/strong&gt;：这是一个用于定义和管理权限的类。开发者可以通过创建&lt;code&gt;Permissions&lt;/code&gt;对象并将其传递给&lt;code&gt;SecurityManager&lt;/code&gt;来设置应用程序的权限集。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;java.security.CodeSource&lt;/strong&gt;：这个类用于表示代码的来源，包括 URL 和证书信息。它与权限控制紧密相关，因为安全管理器可以根据代码来源来授予或拒绝特定的权限。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;沙箱和 Applet API 的弃用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Applet API 在 JDK 11 中被标记为弃用，并在 JDK 14 中被完全移除。Applet 提供了在浏览器中运行 Java 程序的能力，但由于安全问题和现代 Web 技术的发展，它已经不再被推荐使用。随着 Applet API 的弃用，Java 的沙箱模型也得到了重新评估，以确保 Java 应用程序的安全性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;加强的 JVM 安全特性&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JVM 安全沙箱&lt;/strong&gt;：JVM 本身提供了一个安全沙箱，限制了类加载器和类定义的权限。在 JDK 11 及后续版本中，这个沙箱得到了加强，以防止潜在的安全漏洞。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JVM TI（Tool Interface）&lt;/strong&gt;：JVM TI 提供了一组 API，允许监控和控制运行中的 Java 虚拟机。在 JDK 11 中，对 JVM TI 的访问受到了限制，以减少潜在的安全风险。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;安全管理器和权限控制是 Java 平台安全性的关键组成部分。通过不断更新和改进这些机制，Java 确保了应用程序在一个受控的环境中运行，保护了用户的数据和系统资源。随着 Java 技术的不断发展，我们可以期待未来会有更多的安全特性被引入，以应对不断变化的安全威胁和挑战。开发者应当关注这些更新，确保他们的应用程序遵循最新的安全最佳实践。&lt;/p&gt;
&lt;h3 id="启动和打包的新工具和方法"&gt;&lt;a href="#%e5%90%af%e5%8a%a8%e5%92%8c%e6%89%93%e5%8c%85%e7%9a%84%e6%96%b0%e5%b7%a5%e5%85%b7%e5%92%8c%e6%96%b9%e6%b3%95" class="header-anchor"&gt;&lt;/a&gt;启动和打包的新工具和方法
&lt;/h3&gt;&lt;p&gt;随着 Java 生态系统的发展，启动和打包应用程序的方式也在不断演进。为了满足现代应用程序对快速启动和部署的需求，Java 平台引入了一系列新的工具和方法，旨在简化开发流程，提高效率，并支持新的部署模式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;jlink 和 jpackage 工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;jlink（Java Linker）和 jpackage 是 Java 平台提供的新工具，它们使得创建定制的运行时映像和打包应用程序变得更加简单和高效。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;jlink 工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;jlink 工具允许开发者创建一个定制的运行时映像（也称为“链接包”），这个映像包含了运行应用程序所需的最小化的 JVM 组件和应用程序代码。通过这种方式，开发者可以减少运行时的体积，提高启动速度，并减少对系统资源的占用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;减少运行时体积&lt;/strong&gt;：传统的 JRE（Java 运行时环境）包含了许多不常用的功能和组件，这使得其体积相对较大。使用 jlink，开发者可以选择性地包含必要的模块，从而生成一个更小的运行时映像。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提高启动速度&lt;/strong&gt;：较小的运行时映像意味着更少的加载时间，从而提高了应用程序的启动速度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定制化部署&lt;/strong&gt;：jlink 提供了高度的定制化能力，开发者可以根据应用程序的特定需求来构建运行时映像，例如，包含特定的语言包或不包含某些不常用的功能。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;jpackage 工具&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;jpackage 工具是 Java 14 中引入的，用于将 Java 应用程序打包为平台特定的安装包。这个工具支持多种操作系统，包括 Windows、macOS 和 Linux，能够生成如 MSI、EXE、PKG、Deb 和 RPM 等格式的安装包。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;一站式打包&lt;/strong&gt;：jpackage 简化了打包流程，开发者只需一个命令就可以生成适用于目标平台的安装包。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;集成式安装&lt;/strong&gt;：生成的安装包可以集成到操作系统的包管理器中，使得应用程序的安装、更新和卸载与操作系统的其他软件一致。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;支持多种平台&lt;/strong&gt;：jpackage 支持跨平台打包，开发者可以使用相同的源代码生成适用于不同操作系统的安装包。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;使用示例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以下是使用 jlink 和 jpackage 工具的基本示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;使用&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;jlink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;创建定制的运行时映像&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;jlink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;jdk&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;jmods&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;modules&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desktop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;使用&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;jpackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;打包应用程序&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;jpackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;jar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在上述示例中，我们首先使用 jlink 创建了一个只包含必要模块的运行时映像，然后使用 jpackage 将应用程序打包为 Windows 平台的 EXE 安装文件。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;jlink 和 jpackage 工具的引入，为 Java 应用程序的部署提供了更多的灵活性和便捷性。通过这些工具，开发者可以创建定制化的运行时映像和平台特定的安装包，从而满足不同场景下的部署需求。随着 Java 平台的不断发展，我们可以期待未来会有更多的工具和方法来支持现代化的应用程序部署。&lt;/p&gt;
&lt;h3 id="jigsaw-项目和模块系统"&gt;&lt;a href="#jigsaw-%e9%a1%b9%e7%9b%ae%e5%92%8c%e6%a8%a1%e5%9d%97%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;Jigsaw 项目和模块系统
&lt;/h3&gt;&lt;p&gt;Jigsaw 项目是 Java 发展史上的一个重要里程碑，它的目标是将 Java 平台模块化，从而提高 Java 应用程序的性能、安全性和可维护性。Jigsaw 项目的核心是引入了 Java 模块系统（也称为 Project Jigsaw），这是 Java 11 中的一个重要特性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;模块化的好处&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;模块化带来了多个好处，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更清晰的依赖关系&lt;/strong&gt;：模块系统强制定义了包和模块之间的依赖关系，使得依赖更加明确，减少了类路径冲突的可能性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更好的封装&lt;/strong&gt;：模块可以隐藏其内部的实现细节，只暴露必要的 API，从而保护了应用程序的核心代码不被外部直接访问。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更高效的类加载&lt;/strong&gt;：模块系统允许 JVM 有选择地加载和卸载模块，这不仅减少了内存占用，还提高了应用程序的启动速度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更灵活的版本管理&lt;/strong&gt;：模块化使得单独的模块可以独立更新和维护，而不会影响到整个应用程序。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;模块系统的基本概念&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Java 模块系统基于以下几个基本概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;模块&lt;/strong&gt;（Module）：一个模块是一个包含相关类和资源的容器。模块通过&lt;code&gt;module&lt;/code&gt;声明来定义，并在&lt;code&gt;module-info.java&lt;/code&gt;文件中指定。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;依赖&lt;/strong&gt;（Requires）：模块之间通过&lt;code&gt;requires&lt;/code&gt;声明来表达依赖关系。一个模块可以依赖其他模块，并使用这些模块提供的 API。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;导出&lt;/strong&gt;（Exports）：模块可以导出包，使得其他模块可以使用这些包中的类。导出关系通过&lt;code&gt;exports&lt;/code&gt;声明来定义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;打开&lt;/strong&gt;（Opens）：模块可以打开包，允许其他模块访问其内部的类。这通常用于模块间的服务提供者和使用者关系。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;模块系统的使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Java 11 及以上版本中，开发者需要使用模块系统来构建应用程序。以下是一个简单的模块化应用程序的例子：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myapp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;exports&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myapp&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;opens&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;myapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commons&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们定义了一个名为&lt;code&gt;com.example.myapp&lt;/code&gt;的模块，它依赖于&lt;code&gt;com.example.commons&lt;/code&gt;模块和 Java 标准库中的&lt;code&gt;java.sql&lt;/code&gt;模块。我们还导出了&lt;code&gt;com.example.myapp&lt;/code&gt;包给&lt;code&gt;com.example.commons&lt;/code&gt;，并打开了&lt;code&gt;com.example.myapp.internal&lt;/code&gt;包给&lt;code&gt;com.example.commons&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Jigsaw 项目和模块系统的引入标志着 Java 平台在模块化方面的重大进步。模块化不仅提高了代码的组织性和可维护性，还为 Java 应用程序的性能和安全性带来了显著的提升。随着 Java 平台的不断发展，模块系统将继续演进，为开发者提供更多的灵活性和控制力。开发者应当熟悉模块化的概念和最佳实践，以便充分利用这一特性。&lt;/p&gt;
&lt;h2 id="javadoc-和字节码的更新"&gt;&lt;a href="#javadoc-%e5%92%8c%e5%ad%97%e8%8a%82%e7%a0%81%e7%9a%84%e6%9b%b4%e6%96%b0" class="header-anchor"&gt;&lt;/a&gt;Javadoc 和字节码的更新
&lt;/h2&gt;&lt;p&gt;随着 Java 语言和平台的发展，Javadoc 工具和字节码规范也在不断进化，以适应新的编程实践和性能需求。这些更新对于开发者来说至关重要，因为它们影响着代码的文档化、兼容性和执行效率。&lt;/p&gt;
&lt;h3 id="javadoc-的现代化"&gt;&lt;a href="#javadoc-%e7%9a%84%e7%8e%b0%e4%bb%a3%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;Javadoc 的现代化
&lt;/h3&gt;&lt;p&gt;Javadoc 是 Java 开发者用来生成 API 文档的重要工具。在 Java 9 中，Javadoc 工具经历了一次重大更新，引入了多项新特性和改进。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新的文档标签和工具特性&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@thumbnail&lt;/code&gt;标签&lt;/strong&gt;：这个新标签允许开发者在 Javadoc 中嵌入小型图像，增强了文档的可读性和直观性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@implSpec&lt;/code&gt;和&lt;code&gt;@implNote&lt;/code&gt;标签&lt;/strong&gt;：这两个标签分别用于描述实现的意图和注意事项，提供了一种标准化的方式来记录实现细节。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Javadoc 预览特性&lt;/strong&gt;：Java 9 引入了预览特性的概念，允许开发者尝试即将推出的 Javadoc 新特性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;HTML5 和搜索功能的引入&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Javadoc 工具现在支持 HTML5，这意味着生成的文档可以利用现代 Web 技术，提供更好的跨设备兼容性和用户体验。此外，Javadoc 输出现在包括一个搜索框，允许用户快速查找 API 文档中的类、方法和属性。&lt;/p&gt;
&lt;h3 id="字节码的改进和新增"&gt;&lt;a href="#%e5%ad%97%e8%8a%82%e7%a0%81%e7%9a%84%e6%94%b9%e8%bf%9b%e5%92%8c%e6%96%b0%e5%a2%9e" class="header-anchor"&gt;&lt;/a&gt;字节码的改进和新增
&lt;/h3&gt;&lt;p&gt;Java 虚拟机（JVM）的字节码指令集和属性也在不断演进，以支持新的语言特性和性能优化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;动态类生成的改进&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;随着 Java 语言和 API 的发展，动态生成类的能力变得更加重要。例如，Java 9 引入了&lt;code&gt;java.lang.invoke.MethodHandle&lt;/code&gt;的新方法，使得动态类生成更加高效和灵活。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新增的字节码指令和属性&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;invokedynamic&lt;/code&gt;指令&lt;/strong&gt;：这个指令已经在 Java 7 中引入，用于动态解析方法调用，支持动态语言和框架，如 Project Panama。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;新增的类文件属性&lt;/strong&gt;：Java 11 中引入了新的类文件属性，如&lt;code&gt;Module&lt;/code&gt;和&lt;code&gt;ModulePackages&lt;/code&gt;，它们与 Java 模块系统相关联，用于存储模块化的元数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;新增的 Code Attribute&lt;/strong&gt;：Java 11 还引入了新的 Code Attribute，如&lt;code&gt;StackMapTable&lt;/code&gt;，用于增强 JVM 的类型检查和安全性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Javadoc 和字节码的更新反映了 Java 平台对现代软件开发需求的响应。Javadoc 的现代化改进使得 API 文档更加丰富和易用，而字节码的增强则为 Java 语言的新特性和性能优化提供了支持。开发者应当关注这些更新，以便更好地利用 Java 平台提供的工具和特性。随着 Java 技术的不断发展，我们可以期待未来会有更多的创新和改进，进一步丰富 Java 生态系统。&lt;/p&gt;
&lt;h2 id="新支持的平台和版本方案"&gt;&lt;a href="#%e6%96%b0%e6%94%af%e6%8c%81%e7%9a%84%e5%b9%b3%e5%8f%b0%e5%92%8c%e7%89%88%e6%9c%ac%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;新支持的平台和版本方案
&lt;/h2&gt;&lt;p&gt;随着技术的发展和市场需求的变化，Java 平台不断扩展其对新硬件和操作系统的支持。这些更新确保了 Java 应用程序能够在更广泛的设备和环境中运行，同时保持了跨平台兼容性。&lt;/p&gt;
&lt;h3 id="跨平台支持和兼容性"&gt;&lt;a href="#%e8%b7%a8%e5%b9%b3%e5%8f%b0%e6%94%af%e6%8c%81%e5%92%8c%e5%85%bc%e5%ae%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;跨平台支持和兼容性
&lt;/h3&gt;&lt;p&gt;Java 的核心优势之一是其跨平台性，这意味着在不同操作系统和硬件上运行的 Java 虚拟机（JVM）能够提供一致的运行时环境。为了维持这一优势，Java 开发团队持续对 JVM 进行优化，以支持新的处理器架构和操作系统版本。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新增平台的支持情况&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 JDK 8 至 21 的版本中，Java 增加了对多个新平台的支持，包括但不限于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Linux/RISC-V&lt;/strong&gt;：随着 RISC-V 开源处理器架构的兴起，Java 在 JDK 19 中增加了对 Linux/RISC-V 的支持，为开发者在这一新兴平台上构建 Java 应用程序提供了可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;macOS/AArch64&lt;/strong&gt;：随着 Apple 转向自家设计的 ARM 架构处理器，Java 在 JDK 17 中增加了对 macOS/AArch64 的支持，确保了 Java 应用程序能够在新的 Mac 设备上运行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Windows/AArch64&lt;/strong&gt;：同样，为了支持 Windows 操作系统上的 ARM 架构，Java 也在 JDK 16 中增加了对 Windows/AArch64 的支持。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;版本兼容性和升级指南&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了帮助开发者平滑过渡到新版本，Java 提供了详细的版本兼容性指南。这些指南涵盖了从旧版本迁移到新版本的各个方面，包括 API 变更、废弃特性和新的模块系统。开发者可以参照这些指南来更新他们的应用程序，以利用新版本的特性和性能改进。&lt;/p&gt;
&lt;h3 id="版本命名方案的变更"&gt;&lt;a href="#%e7%89%88%e6%9c%ac%e5%91%bd%e5%90%8d%e6%96%b9%e6%a1%88%e7%9a%84%e5%8f%98%e6%9b%b4" class="header-anchor"&gt;&lt;/a&gt;版本命名方案的变更
&lt;/h3&gt;&lt;p&gt;Java 的版本命名方案在 JDK 9 中经历了重大变化。在此之前，Java 的版本号遵循主版本号。次版本号的模式（例如，1.8 表示 JDK 8）。从 JDK 9 开始，Java 采用了新的命名方案，其中版本号包括了年份和更新次数（例如，9 表示 2017 年的更新版本）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新版本命名的逻辑&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新版本命名的逻辑旨在简化版本号的管理，并与 Java 的发布节奏保持一致。每个版本号都反映了它发布的时间，这使得开发者和用户能够更容易地了解他们使用的 Java 版本相对于其他版本的年龄。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;版本迭代的速度和周期&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自 JDK 9 以来，Java 的版本迭代速度加快，每六个月发布一个新的版本。这种快速迭代的模式使得 Java 能够更快地引入新特性和改进，同时也意味着开发者和用户需要更频繁地更新他们的 Java 环境。为了适应这种快速迭代，Java 也引入了长期支持（LTS）版本，这些版本会得到更长时间的支持和维护，适合需要稳定性和长期支持的企业级应用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;新支持的平台和版本方案的变更体现了 Java 对不断变化的技术环境的适应性。通过增加对新硬件和操作系统的支持，Java 确保了其跨平台优势的持续存在。同时，新的版本命名方案和快速迭代模式使得 Java 能够更快地响应开发者的需求，推动 Java 生态系统的持续发展。开发者应当关注这些变化，以确保他们的应用程序能够充分利用 Java 平台的最新特性和改进。&lt;/p&gt;
&lt;h2 id="弃用和移除的特性"&gt;&lt;a href="#%e5%bc%83%e7%94%a8%e5%92%8c%e7%a7%bb%e9%99%a4%e7%9a%84%e7%89%b9%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;弃用和移除的特性
&lt;/h2&gt;&lt;p&gt;随着 Java 平台的发展，某些旧特性可能会因为安全问题、更好的替代方案或者技术进步而变得过时。为了保持语言的现代化和高效性，Java 开发团队会定期审查和弃用这些特性，并在适当的时候将其移除。这一过程需要仔细的规划和透明的沟通，以确保开发者有足够的时间来适应变化。&lt;/p&gt;
&lt;h3 id="弃用列表和未来展望"&gt;&lt;a href="#%e5%bc%83%e7%94%a8%e5%88%97%e8%a1%a8%e5%92%8c%e6%9c%aa%e6%9d%a5%e5%b1%95%e6%9c%9b" class="header-anchor"&gt;&lt;/a&gt;弃用列表和未来展望
&lt;/h3&gt;&lt;p&gt;Java 社区维护了一个详细的弃用特性列表，这个列表随着每个新版本的发布而更新。开发者可以通过查阅这个列表来了解哪些特性已被弃用，以及它们的未来状态。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Java EE 的移除&lt;/strong&gt;：Java 企业版（Java EE）在 JDK 11 中被移除，转而作为独立的 Eclipse 项目继续发展。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CORBA 模块的移除&lt;/strong&gt;：Java 的 CORBA 支持在 JDK 11 中被移除，因为这项技术的使用已经变得较少。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nashorn JavaScript 引擎的移除&lt;/strong&gt;：在 JDK 15 中，Nashorn JavaScript 引擎被标记为弃用，并在 JDK 11 中被完全移除。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;移除特性的影响和替代方案&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;移除特性会对依赖这些特性的应用程序产生影响。因此，Java 提供了替代方案，以帮助开发者平滑过渡到新的技术。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Java EE 的替代方案&lt;/strong&gt;：对于 Java EE 的替代，开发者可以转向 Spring Boot、Quarkus 等现代框架，它们提供了类似的功能，并且更加轻量级和灵活。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CORBA 的替代方案&lt;/strong&gt;：对于需要 RPC（远程过程调用）的开发者，可以考虑使用 gRPC 或 RESTful 服务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Nashorn 的替代方案&lt;/strong&gt;：对于需要在 Java 中执行 JavaScript 的开发者，可以考虑使用 GraalVM 的 JavaScript 引擎。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;向后兼容性的挑战&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;向后兼容性是 Java 平台的一个重要原则，它确保了旧代码在新版本中仍然能够正常运行。然而，移除特性的决定可能会对向后兼容性造成挑战。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;向后兼容性的策略&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为了最小化对现有应用程序的影响，Java 开发团队采取了一系列策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;清晰的弃用周期&lt;/strong&gt;：Java 提供了清晰的弃用周期，通常在特性被完全移除之前会有一个警告期。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提供替代方案&lt;/strong&gt;：Java 努力为每个被弃用的特性提供替代方案，以帮助开发者进行迁移。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;逐步移除&lt;/strong&gt;：对于大型特性，Java 可能会逐步移除，先将其标记为弃用，然后在后续版本中完全移除。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="开发者如何应对弃用和移除"&gt;&lt;a href="#%e5%bc%80%e5%8f%91%e8%80%85%e5%a6%82%e4%bd%95%e5%ba%94%e5%af%b9%e5%bc%83%e7%94%a8%e5%92%8c%e7%a7%bb%e9%99%a4" class="header-anchor"&gt;&lt;/a&gt;开发者如何应对弃用和移除
&lt;/h3&gt;&lt;p&gt;开发者应当密切关注 Java 社区的更新和公告，了解哪些特性正在被弃用或计划被移除。对于正在使用的弃用特性，开发者应该：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;评估影响&lt;/strong&gt;：分析应用程序中使用弃用特性的代码，评估迁移的成本和影响。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;制定迁移计划&lt;/strong&gt;：根据评估结果，制定详细的迁移计划，包括时间表和技术路线。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;测试和验证&lt;/strong&gt;：在迁移到新特性或替代方案后，进行充分的测试以确保应用程序的功能和性能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更新文档和培训&lt;/strong&gt;：更新内部文档，并为团队成员提供必要的培训，以确保所有人都了解新的变化。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过这些措施，开发者可以确保他们的应用程序能够适应 Java 平台的变化，同时保持高效和稳定。&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;在对 Java 平台从 JDK 8 至 21 的演进进行深入探讨后，我们可以总结出几个关键点，这些点不仅展示了 Java 语言和生态系统的发展，也为开发者提供了未来工作的方向和策略。&lt;/p&gt;
&lt;h3 id="语言特性的进步"&gt;&lt;a href="#%e8%af%ad%e8%a8%80%e7%89%b9%e6%80%a7%e7%9a%84%e8%bf%9b%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;语言特性的进步
&lt;/h3&gt;&lt;p&gt;Java 语言在这段时间里经历了显著的增强，包括引入了函数式编程概念、模式匹配、未命名变量和模式、封闭类和记录类等。这些新特性不仅丰富了 Java 的表达能力，也使得代码更加简洁、可读性更强，同时提高了开发效率。&lt;/p&gt;
&lt;h3 id="api-的扩展和更新"&gt;&lt;a href="#api-%e7%9a%84%e6%89%a9%e5%b1%95%e5%92%8c%e6%9b%b4%e6%96%b0" class="header-anchor"&gt;&lt;/a&gt;API 的扩展和更新
&lt;/h3&gt;&lt;p&gt;Java 标准库的扩展和更新为开发者提供了新的工具和能力。集合和数学函数 API 的增强、文件和 IO 操作的改进、网络编程的新特性以及安全管理器和权限控制的更新，都使得 Java 应用程序能够更好地处理复杂的任务和安全挑战。&lt;/p&gt;
&lt;h3 id="性能和资源管理的优化"&gt;&lt;a href="#%e6%80%a7%e8%83%bd%e5%92%8c%e8%b5%84%e6%ba%90%e7%ae%a1%e7%90%86%e7%9a%84%e4%bc%98%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;性能和资源管理的优化
&lt;/h3&gt;&lt;p&gt;Java 虚拟机的性能和资源管理一直是 Java 开发的重点。JIT 编译器的优化、垃圾回收器的进步、内存管理和启动时间的改进，都显著提高了 Java 应用程序的运行效率和用户体验。&lt;/p&gt;
&lt;h3 id="模块化和跨平台支持"&gt;&lt;a href="#%e6%a8%a1%e5%9d%97%e5%8c%96%e5%92%8c%e8%b7%a8%e5%b9%b3%e5%8f%b0%e6%94%af%e6%8c%81" class="header-anchor"&gt;&lt;/a&gt;模块化和跨平台支持
&lt;/h3&gt;&lt;p&gt;Jigsaw 项目的完成和模块系统的引入，标志着 Java 平台在模块化方面取得了重大进展。这不仅提高了 Java 的内在质量和可维护性，也简化了应用程序的部署和分发。同时，Java 对新平台的支持，如 RISC-V 和 AArch64，确保了 Java 在多样化的计算环境中的持续相关性。&lt;/p&gt;
&lt;h3 id="向后兼容性的维护"&gt;&lt;a href="#%e5%90%91%e5%90%8e%e5%85%bc%e5%ae%b9%e6%80%a7%e7%9a%84%e7%bb%b4%e6%8a%a4" class="header-anchor"&gt;&lt;/a&gt;向后兼容性的维护
&lt;/h3&gt;&lt;p&gt;Java 社区对向后兼容性的承诺保证了新版本可以无缝地与现有代码库协同工作。尽管一些特性被弃用或移除，但 Java 提供了清晰的路线图和替代方案，以帮助开发者平滑过渡。&lt;/p&gt;
&lt;h3 id="未来展望"&gt;&lt;a href="#%e6%9c%aa%e6%9d%a5%e5%b1%95%e6%9c%9b" class="header-anchor"&gt;&lt;/a&gt;未来展望
&lt;/h3&gt;&lt;p&gt;随着 Java 的不断发展，我们可以预见到更多的创新和改进。新的语言特性、API 和性能优化将继续出现，以适应新的编程范式和技术趋势。同时，Java 社区将继续致力于提高平台的安全性、可维护性和用户友好性。&lt;/p&gt;
&lt;p&gt;对于开发者来说，保持对 Java 新特性和最佳实践的了解至关重要。通过不断学习和适应变化，开发者可以确保他们的技能和应用程序保持最新，从而在不断变化的技术环境中保持竞争力。随着 Java 生态系统的不断壮大，Java 将继续作为企业级应用程序和现代云服务的坚实基础，引领软件开发的未来。&lt;/p&gt;</description></item><item><title>信息成瘾如何悄悄控制你的生活</title><link>https://xiaobox.github.io/p/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/</link><pubDate>Fri, 23 Feb 2024 07:56:20 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/cover.jpg" alt="Featured image of post 信息成瘾如何悄悄控制你的生活" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;“成瘾是一种脑部疾病，其特征是强迫性地参与奖励刺激，尽管有不良后果。”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/001-3130fe54.png"&gt;&lt;/p&gt;
&lt;h2 id="什么是信息成瘾"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af%e4%bf%a1%e6%81%af%e6%88%90%e7%98%be" class="header-anchor"&gt;&lt;/a&gt;什么是信息成瘾？
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;信息成瘾是一种由不负责任地消费信息引起的疾病，尤其是强迫性消费。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不断地刷新微博，即使你已经看过了所有内容。&lt;/li&gt;
&lt;li&gt;关了抖音又立即再次打开它。&lt;/li&gt;
&lt;li&gt;每五分钟拿起你的手机看有没有新的消息，不断分心期待它们，以及当手机不在你身边时你感到的焦虑。&lt;/li&gt;
&lt;li&gt;当有新消息时，你会有紧迫感并且兴高采烈。&lt;/li&gt;
&lt;li&gt;不断自恋地查看新发布的朋友圈有没有人点赞&lt;/li&gt;
&lt;li&gt;偶尔想看会儿书，最终却刷了 2 小时短视频&lt;/li&gt;
&lt;li&gt;迫不及待地打开今日头条想了解世界上发生了什么事，你对世界上发生了什么事情而自己不知道感觉很焦虑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当你经历过这一切后，总结来说，你感觉到不舒服和不满意，明知道浪费了时间深深自责的同时又无法控制，“下次一定” 永远停留在下一次。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;你的灵魂在哭泣，就像被拴在一只绕圈跑的老鼠身上。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="这有点像食物"&gt;&lt;a href="#%e8%bf%99%e6%9c%89%e7%82%b9%e5%83%8f%e9%a3%9f%e7%89%a9" class="header-anchor"&gt;&lt;/a&gt;这有点像食物
&lt;/h3&gt;&lt;p&gt;吃饭是生活的现实，处理信息也是如此。你也无法避免，但如果你和他们的关系不好，他们会毁了你。&lt;/p&gt;
&lt;p&gt;在许多方面，信息比食物更危险。选择吃饭需要努力 —— 你必须走到厨房、点菜或去购物。信息毫不费力。附近总有一个屏幕。&lt;/p&gt;
&lt;p&gt;食物还有一个明显的身体后果：吃的太多，你会立即感到恶心，从长远来看，你会变得肥胖。信息会让你的大脑一片狼藉，但这更容易被忽视，甚至在一个以信息为常态的社会中被接受。&lt;/p&gt;
&lt;p&gt;现在，我们越来越依赖信息，我们与越来越令人上瘾和危险的信息源互动。&lt;/p&gt;
&lt;p&gt;识别你何时被条件反射的卑鄙本能拖累，是一项越来越重要的生存技能。&lt;/p&gt;
&lt;p&gt;当你吃饱时，你不会再吃掉两个蛋糕。你的饮食不仅仅是垃圾食品。你也可以学会负责任地使用信息。&lt;/p&gt;
&lt;h2 id="信息成瘾的影响"&gt;&lt;a href="#%e4%bf%a1%e6%81%af%e6%88%90%e7%98%be%e7%9a%84%e5%bd%b1%e5%93%8d" class="header-anchor"&gt;&lt;/a&gt;信息成瘾的影响
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;它消耗了您的时间和精力&lt;/li&gt;
&lt;li&gt;它分散了你的注意力，使你永远分心，剥夺了你的注意力，使你更难追求复杂和深层。&lt;/li&gt;
&lt;li&gt;它麻痹了你的生活体验，让你对你的现实互动不那么关心和感觉。&lt;/li&gt;
&lt;li&gt;它把你塑造成一个冲动行事的人，并让你在行动中放弃独立思考和自主判断&lt;/li&gt;
&lt;li&gt;根据你的 “偏好”，它会加强你的认知缺陷和偏见&lt;/li&gt;
&lt;li&gt;它大大助长了悲观主义、抑郁、厌世、宿命论和虚无主义。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="你是否沉迷于信息"&gt;&lt;a href="#%e4%bd%a0%e6%98%af%e5%90%a6%e6%b2%89%e8%bf%b7%e4%ba%8e%e4%bf%a1%e6%81%af" class="header-anchor"&gt;&lt;/a&gt;你是否沉迷于信息？
&lt;/h3&gt;&lt;p&gt;信息成瘾会让你麻木到感觉不到它影响的地步，因为感觉的能力会枯萎。&lt;/p&gt;
&lt;h2 id="因果关系"&gt;&lt;a href="#%e5%9b%a0%e6%9e%9c%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;因果关系
&lt;/h2&gt;&lt;p&gt;如果你的生活看起来很严峻；如果你的财务状况很糟糕，很难找到工作，感觉无能为力，或者如果你生活中的某些东西限制了你，信息成瘾对逃避现实是非常有吸引力的。&lt;/p&gt;
&lt;p&gt;随着信息成瘾的加深，你对个人健康（卫生、睡眠、食物、运动）、家务（清洁、整理、购物）和金钱的追求都会逐渐忽视，对于所有延迟回报的事情都不看好。&lt;/p&gt;
&lt;p&gt;你的思想被一百个小声音所支配，吵着要他们最喜欢的东西，你失去了对自己的掌控。&lt;/p&gt;
&lt;h3 id="屏幕无处不在"&gt;&lt;a href="#%e5%b1%8f%e5%b9%95%e6%97%a0%e5%a4%84%e4%b8%8d%e5%9c%a8" class="header-anchor"&gt;&lt;/a&gt;屏幕，无处不在
&lt;/h3&gt;&lt;p&gt;这就像试图在打火机和香烟散落一地的房子里戒烟一样。这是一个疯狂的要求，所以，要让屏幕成为你生活中的一小部分，而不是一大部分。&lt;/p&gt;
&lt;h3 id="疲惫"&gt;&lt;a href="#%e7%96%b2%e6%83%ab" class="header-anchor"&gt;&lt;/a&gt;疲惫
&lt;/h3&gt;&lt;p&gt;你有可能忙了一天，终于有一段休息的时间时，会拿起手机 “放松” 一下，这时候你疲惫的大脑更加无法抵御信息成瘾这样的问题。&lt;/p&gt;
&lt;p&gt;你需要有一个合理的心态来处理这些东西。这意味着要抽出平静、休息的时间。尽你所能。但你也不需要对这些东西绝对化，就像我们虽然也追求良好的饮食习惯，但偶尔吃一顿垃圾食品也没什么大不了的。&lt;/p&gt;
&lt;h2 id="人际关系"&gt;&lt;a href="#%e4%ba%ba%e9%99%85%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;人际关系
&lt;/h2&gt;&lt;p&gt;逐渐减少使用可以让你从更少的信息成瘾中受益，同时优雅地减少你的连接状态&lt;/p&gt;
&lt;p&gt;与他人共度时光是我们社交的核心。信息成瘾习惯可能会使你远离与朋友共度时光，而缺乏可以共度时光的人可能会将你推向信息成瘾。&lt;/p&gt;
&lt;p&gt;信息成瘾会麻木和分散注意力，以至于缺乏联系的痛苦不那么严重。&lt;/p&gt;
&lt;h2 id="心理"&gt;&lt;a href="#%e5%bf%83%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;心理
&lt;/h2&gt;&lt;h3 id="注意力碎片化"&gt;&lt;a href="#%e6%b3%a8%e6%84%8f%e5%8a%9b%e7%a2%8e%e7%89%87%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;注意力碎片化
&lt;/h3&gt;&lt;p&gt;注意力碎片化是一种生物，当你花太长时间被通知等事物打断时，它就会诞生。&lt;/p&gt;
&lt;p&gt;最终，你进入了一种永久分心的状态，在这种状态下，你大脑的大部分内容不断地期待（兴奋或恐惧）下一次中断。你有限的同时处理能力储备被这些客人耗尽了，这就是焦虑让你失去理智的原因，并使你更有可能做出低质量的决定。&lt;/p&gt;
&lt;h3 id="体验性麻木"&gt;&lt;a href="#%e4%bd%93%e9%aa%8c%e6%80%a7%e9%ba%bb%e6%9c%a8" class="header-anchor"&gt;&lt;/a&gt;体验性麻木
&lt;/h3&gt;&lt;p&gt;体验性麻木有点远，但如果你到目前为止一直在点头，我怀疑你会知道我在说什么。&lt;/p&gt;
&lt;p&gt;你每天有有限的高质量精神能量储备。如果你把很大一部分时间花在一种破坏性的、信息成瘾上，你就会感到麻木，因为这种储备已经耗尽了。如果你一直透支它，你就会逐渐失去补充它的能力。这需要很长时间才能愈合。&lt;/p&gt;
&lt;p&gt;你可能会丧失惊奇、喜悦、悲伤、生动、自发和创造力。你周围的世界失去色彩并不是因为它自己的错。在多年的时间里，你花在各种引人注目的信息水龙头上，只关心下一个点击，你失去了欣赏世界的敏感性。&lt;/p&gt;
&lt;p&gt;这是一个很难描述的问题，因为损害是微妙的和渐进的，就像温水煮青蛙一样。&lt;/p&gt;
&lt;p&gt;大多数患者没有意识到或关心他们患有这种疾病。也许事情变得无聊得更快，你已经远离了对事物的内在敬畏。并且你已经习惯了。&lt;/p&gt;
&lt;h3 id="感到不知所措"&gt;&lt;a href="#%e6%84%9f%e5%88%b0%e4%b8%8d%e7%9f%a5%e6%89%80%e6%8e%aa" class="header-anchor"&gt;&lt;/a&gt;感到不知所措
&lt;/h3&gt;&lt;p&gt;信息洪流是无情的。这会在不同的人身上产生不同的东西。&lt;/p&gt;
&lt;p&gt;有些人 “正面” 迎接它，将大量时间用于确保他们尽可能多地消费，这样他们就不会被抛在后面。这是通往注意力碎片化和体验麻木的快速途径。&lt;/p&gt;
&lt;p&gt;有些人试图经受住或扭转潮流，但可能仍然在保持理智和放弃理智之间挣扎。&lt;/p&gt;
&lt;p&gt;无论你是哪一种， 都不是一种健康的体验。&lt;/p&gt;
&lt;h3 id="缺陷和偏见"&gt;&lt;a href="#%e7%bc%ba%e9%99%b7%e5%92%8c%e5%81%8f%e8%a7%81" class="header-anchor"&gt;&lt;/a&gt;缺陷和偏见
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;灾难偏见。危险使我们振作起来。仅凭这种偏见就解释了悲观主义的流行，在这个世界上，从数字上看，情况比以往任何时候都好：媒体卷入了一场争夺我们注意力的竞赛，依靠 “一切都很糟糕” 是他们最好的武器之一。&lt;/li&gt;
&lt;li&gt;其他偏见。在通过我们与群体中其他人的相似性来定义我们的从属关系时，我们也定义了存在于它之外的人。对这些其他人感到非理性的恐惧或蔑视是很容易做到的。渴望权力的政客和渴望观点的媒体依靠这一点来让我们顺从。&lt;/li&gt;
&lt;li&gt;+1 偏见。无论是点赞、转发、收藏、100 金币还是 20 颗宝石，大脑中一个奇怪的部分都喜欢看到好数字上升。如果你曾经玩过点击游戏，你就会知道这个兔子洞的可利用性有多深。&lt;strong&gt;社会的风气倾向于虚荣，他们都在颂扬贪婪&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;连接喜爱。我们是群居动物。这是一种需要。断开连接很糟糕。这种对联系的渴望被大多数社交媒体平台所利用，你可以争辩说它们确实提供了一些有价值的东西 —— 但这是一种苍白的、淡化的联系，而且它是一种经常被不道德地使用的钩子。&lt;/li&gt;
&lt;li&gt;确认偏见。与 + 1 偏差和连接偏差是亲兄弟，我们喜欢被告知我们做得很好。社交 “点赞” 机制正是击中了这一点，但任何形式的祝贺性语言也有同样的效果。这可能是推动社交媒体增长的主要因素之一。当它变成了一个自为目的的终点时，就变得代价高昂，它让我们恰好去做那些能获得最多确认的事情 —— 创造出我们居住其中的不真实的角色，而这些角色反过来又加剧了我们的不足感&lt;/li&gt;
&lt;li&gt;相关性偏差。你已经知道你在意的事情更可能引起你的兴趣。这可能听起来无害，但是那些旨在 “最大化相关性” 的系统会产生过滤泡沫，这使得我们只能听到来自狭小领域、人群，尤其是文化价值观的信息。&lt;/li&gt;
&lt;li&gt;便捷性偏见。这种偏差源于无法深入和复杂。信息成瘾（信息获取的便捷性）通常与一种奇怪的狂热懒惰并存，这种懒惰对哪怕需要最少量努力的事情都感到畏缩，仿佛努力最小化会提高生活质量。因此，如果某件事只是一个简单的点击或者三个步骤，它就会成为一个更有吸引力的选择。这种轻松往往是有代价的，比如错过了你以艰难的方式去做的理解，同意剥削性的条款，或者把你的世界的控制权交给运行 Web 服务和云的公司。&lt;/li&gt;
&lt;li&gt;完成主义强迫症。打卡、收集&amp;hellip;&lt;/li&gt;
&lt;li&gt;生动性偏差。犀利有力的语言、密集而引人入胜的音乐、高度对比鲜明的色彩、精心制作的布景、情感丰富的对话和狂躁的动作场面都在创意作品中占有一席之地。对比度是赋予丰富性的关键，而这些东西是光谱的强端。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="信息成瘾是如何被利用的"&gt;&lt;a href="#%e4%bf%a1%e6%81%af%e6%88%90%e7%98%be%e6%98%af%e5%a6%82%e4%bd%95%e8%a2%ab%e5%88%a9%e7%94%a8%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;信息成瘾是如何被利用的？
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/002-8a6cd4b4.png"&gt;&lt;/p&gt;
&lt;h3 id="进度系统"&gt;&lt;a href="#%e8%bf%9b%e5%ba%a6%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;进度系统
&lt;/h3&gt;&lt;p&gt;这些功能在电脑游戏中最为突出。他们或多或少地根据你玩了多长时间的单一事实向你承诺很酷的东西。进步通常以力量的味道出现 —— 更多的枪、更大的枪、能力或荣誉。&lt;/p&gt;
&lt;h3 id="无情的通知"&gt;&lt;a href="#%e6%97%a0%e6%83%85%e7%9a%84%e9%80%9a%e7%9f%a5" class="header-anchor"&gt;&lt;/a&gt;无情的通知
&lt;/h3&gt;&lt;p&gt;最阴险的应用程序会不断通知你 —— 不会频繁到让您感到烦恼，但也不会不频繁到让您关闭应用程序的侵扰。如果真的有效，每次通知都会吸引你。这加强了你对新应用或程序的熟悉度，并鼓励你进行投入。&lt;/p&gt;
&lt;h3 id="社交媒体"&gt;&lt;a href="#%e7%a4%be%e4%ba%a4%e5%aa%92%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;社交媒体
&lt;/h3&gt;&lt;p&gt;它无情地利用了我们对联系和验证的喜爱，为我们提供了与我们关心的人相处的时间的苍白模仿，同时它吸引我们在现实生活中花更少的时间在一起。&lt;/p&gt;
&lt;p&gt;它夸大了灾难偏见，因为它的内容浮现算法意味着你只能看到前百分之一的 “值得反应” 的内容。&lt;/p&gt;
&lt;h3 id="新闻"&gt;&lt;a href="#%e6%96%b0%e9%97%bb" class="header-anchor"&gt;&lt;/a&gt;新闻
&lt;/h3&gt;&lt;p&gt;新闻因观点而兴旺。这是新闻共享组织生存的唯一途径。记者和编辑很清楚我们的偏见，他们知道该怎么做才能获得点击率和浏览量。&lt;/p&gt;
&lt;p&gt;新闻非常非常强烈地倾向于灾难偏见，并因此向我们展示了一种扭曲的世界观&lt;/p&gt;
&lt;h3 id="游戏"&gt;&lt;a href="#%e6%b8%b8%e6%88%8f" class="header-anchor"&gt;&lt;/a&gt;游戏
&lt;/h3&gt;&lt;p&gt;我认为游戏是我们开发的最令人上瘾的基于屏幕的体验。它们具有很强的互动性，是通往陌生、生动世界的门户。逃避现实从未如此有趣。&lt;/p&gt;
&lt;p&gt;但从广义上讲，桌面游戏存在 “更严重” 的成瘾风险。改进的输入方案、直立坐在座位上以及现代台式 PC 的强大功能意味着你可以体验和访问真正身临其境和高保真度的世界。&lt;/p&gt;
&lt;p&gt;如果你对一个移动游戏有些许投入，你也很容易在想 “消磨时间” 时掏出来玩上一局。&lt;/p&gt;
&lt;h3 id="视频"&gt;&lt;a href="#%e8%a7%86%e9%a2%91" class="header-anchor"&gt;&lt;/a&gt;视频
&lt;/h3&gt;&lt;p&gt;视频可能不是交互式的，但这让它们可以讲述更复杂、由作者主导的故事，这可能更加引人入胜。不需要输入也意味着它们的进入门槛更低。一旦开始观看，您可以根据自己的喜好投入任意多的精神能量 —— 直至 “几乎没有”&lt;/p&gt;
&lt;p&gt;视频内容种类繁多，而且由于它通常充满了信息，因此你一定能找到一些可以强化您的观点、信念或感受的内容&lt;/p&gt;
&lt;p&gt;视频可以展示人们做事、生活、工作、放松。替代性地体验他人的生活（真实的或虚构的）真的会让人上瘾，特别是如果你在生活中缺乏联系，并且不需要想象。&lt;/p&gt;
&lt;h3 id="聊天"&gt;&lt;a href="#%e8%81%8a%e5%a4%a9" class="header-anchor"&gt;&lt;/a&gt;聊天
&lt;/h3&gt;&lt;p&gt;现代消息传递应用程序提供了一种与人们交谈的新方式：同时与 5 人、10 人或 50 人进行持续的低带宽、低承诺讨论。&lt;/p&gt;
&lt;p&gt;你正在这些上下文之间快速切换你的注意力，如果你打开通知，你就会不断地退出你所处的任何现实生活中的上下文来输入它们。这有可能引起大规模的注意力碎片化，因为它对我们有限的日常处理能力提出了要求。&lt;/p&gt;
&lt;h3 id="花钱"&gt;&lt;a href="#%e8%8a%b1%e9%92%b1" class="header-anchor"&gt;&lt;/a&gt;花钱
&lt;/h3&gt;&lt;p&gt;买东西真的会让人上瘾。记住营销是如何运作的。他们是为了说服你，你错过了一些东西，或者你在某种程度上是不够的，他们的产品会给你你 “需要” 的东西。&lt;/p&gt;
&lt;p&gt;如果你有可支配收入，而你的冲动购买只是偶尔的，你可能没问题。但是，如果资金紧张，或者你经常买东西（特别是为了感觉更好），你需要解决它。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果有时间压力，永远不要买任何东西。总是拒绝压力附带的提议，给自己时间反思它是否能真正丰富你的生活。将 “对不起，不行” 作为你的默认答案。&lt;/li&gt;
&lt;li&gt;你可能不需要它。走出兴奋的泡沫，试着弄清楚它将如何影响你的生活，现实的、实用的、日常的。&lt;/li&gt;
&lt;li&gt;花很多时间试图了解你的动机。你为什么想要这个东西？社会认可？完成主义？如果是某种不安全感，问问它是否真的是你自己想要的&lt;/li&gt;
&lt;li&gt;了解价值挂钩。忽略 “原价” 和 “降价”，根据它是什么和它的要价来判断它。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="如何修复信息成瘾"&gt;&lt;a href="#%e5%a6%82%e4%bd%95%e4%bf%ae%e5%a4%8d%e4%bf%a1%e6%81%af%e6%88%90%e7%98%be" class="header-anchor"&gt;&lt;/a&gt;如何修复信息成瘾
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-02-23-xin-xi-cheng-yin-ru-he-qiao-qiao-kong-zhi-ni-de-sheng-huo/003-8cccdfbe.png"&gt;&lt;/p&gt;
&lt;p&gt;你的任务很困难，也很简单。了解你的信息 “饮食习惯”，培养并控制你的消费习惯，并以高标准要求自己。&lt;/p&gt;
&lt;h3 id="质量至关重要"&gt;&lt;a href="#%e8%b4%a8%e9%87%8f%e8%87%b3%e5%85%b3%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;质量至关重要
&lt;/h3&gt;&lt;p&gt;关键的一步是开始评估你所参与的每个信息块的质量。到底一顿精美的大餐还是廉价的外卖，你需要区别对待。&lt;/p&gt;
&lt;h3 id="数量很重要"&gt;&lt;a href="#%e6%95%b0%e9%87%8f%e5%be%88%e9%87%8d%e8%a6%81" class="header-anchor"&gt;&lt;/a&gt;数量很重要
&lt;/h3&gt;&lt;p&gt;整体上摄入过多确实会损害体验敏感性并导致注意力碎片化。把每一天都当成是有限预算，然后在每次与信息互动时做出有意识的选择。当你选择参与时，请全神贯注地去做。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;了解你的缺点；了解他们的工具&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="保持警惕"&gt;&lt;a href="#%e4%bf%9d%e6%8c%81%e8%ad%a6%e6%83%95" class="header-anchor"&gt;&lt;/a&gt;保持警惕
&lt;/h3&gt;&lt;p&gt;您还需要保持内心警惕，因为识别信息成瘾的最佳方法通常是注意自己身上的非理性情绪或冲动行为并寻找其来源。&lt;/p&gt;
&lt;h3 id="有意识"&gt;&lt;a href="#%e6%9c%89%e6%84%8f%e8%af%86" class="header-anchor"&gt;&lt;/a&gt;有意识
&lt;/h3&gt;&lt;p&gt;在打开应用程序或网站之前，告诉自己它是什么 - 大声说出来。&lt;/p&gt;
&lt;p&gt;确保在使用 信息源的整个过程中牢记你的目标。&lt;/p&gt;
&lt;p&gt;这完全重新构建了从 “带我掉进兔子洞” 到 “为我做一些具体的事情” 的互动。它把力量还给你，使你不再是一个被动的消费者。&lt;/p&gt;
&lt;h3 id="你需要一个详尽的具体的计划"&gt;&lt;a href="#%e4%bd%a0%e9%9c%80%e8%a6%81%e4%b8%80%e4%b8%aa%e8%af%a6%e5%b0%bd%e7%9a%84%e5%85%b7%e4%bd%93%e7%9a%84%e8%ae%a1%e5%88%92" class="header-anchor"&gt;&lt;/a&gt;你需要一个详尽的、具体的计划
&lt;/h3&gt;&lt;p&gt;我在自己的信息成瘾治疗中发现，硬时间块对我来说效果非常好。我选择短期的、特定的时间段，在此期间我可以随心所欲地使用任何信息源，这有助于我避免遗漏的方面。在那些时期之外，我不会碰它们。&lt;/p&gt;
&lt;h2 id="对自己要有耐心"&gt;&lt;a href="#%e5%af%b9%e8%87%aa%e5%b7%b1%e8%a6%81%e6%9c%89%e8%80%90%e5%bf%83" class="header-anchor"&gt;&lt;/a&gt;对自己要有耐心
&lt;/h2&gt;&lt;h3 id="时间是你的盟友"&gt;&lt;a href="#%e6%97%b6%e9%97%b4%e6%98%af%e4%bd%a0%e7%9a%84%e7%9b%9f%e5%8f%8b" class="header-anchor"&gt;&lt;/a&gt;时间是你的盟友
&lt;/h3&gt;&lt;p&gt;改变习惯需要时间。解决这个问题几乎没有办法。如果你能理解你的成瘾的形状，并每天远离它，你的胜利就已经稳固了。&lt;/p&gt;
&lt;p&gt;你的超能力是适应和成长的能力。用反思来迎接失败 —— 这是一个成长的机会 —— 并对你正在取得的进步感到满意。&lt;/p&gt;
&lt;p&gt;失败得足够多，你就一定会成功。&lt;/p&gt;
&lt;h3 id="原谅自己"&gt;&lt;a href="#%e5%8e%9f%e8%b0%85%e8%87%aa%e5%b7%b1" class="header-anchor"&gt;&lt;/a&gt;原谅自己
&lt;/h3&gt;&lt;p&gt;如果你做得不好，你很容易在自怜或自我厌恶的漩涡中迷失自己，特别是如果你最近表现不佳。尽量避免诱惑。一个月后，当你没有任何进展时，你可能感觉很糟。但这并不丢人。原谅自己，没关系的。&lt;/p&gt;
&lt;h2 id="避免坏习惯"&gt;&lt;a href="#%e9%81%bf%e5%85%8d%e5%9d%8f%e4%b9%a0%e6%83%af" class="header-anchor"&gt;&lt;/a&gt;避免坏习惯
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;尽可能避免使用屏幕。养成一个一揽子的习惯，在求助于屏幕之前，先寻找在屏幕外做事的方法，并追求没有屏幕的爱好和休闲活动。注意所有屏幕时间，并努力将其降至最低。应用程序可以在这方面提供帮助。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果您的工作需要屏幕，请锁定该计算机，使其只做一件事。将娱乐时间花在非数字上。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;让你的手机难以取用。把它放在袋子里旅行。坐下后，让它离得足够远，你必须站起来与它互动&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;永远不要让你的手机靠近你的床。如果您在卧室中需要它作为闹钟，请将其放在房间的另一侧。买一个传统的闹钟。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不要在公司里碰手机。如果必须，请保持简短。尊重房间里的人的时间和注意力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;睡前两小时内不要看屏幕&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;健康饮食。每天做饭。减少淀粉和糖的摄入量，减少精制糖的摄入，多吃蔬菜。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;获得充足的优质睡眠。对于数量，你需要遵守纪律。八个小时是一个硬性的最低要求，但九小时更好。质量也很重要。晚上睡觉比较好。干扰、环境光和声音以及不舒服的床垫都会使您的睡眠更差。尽你所能改进。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="填补新的空闲时间"&gt;&lt;a href="#%e5%a1%ab%e8%a1%a5%e6%96%b0%e7%9a%84%e7%a9%ba%e9%97%b2%e6%97%b6%e9%97%b4" class="header-anchor"&gt;&lt;/a&gt;填补新的空闲时间
&lt;/h2&gt;&lt;p&gt;如果你感到无聊和无所事事，你很容易回到信息成瘾。我们人类喜欢做事。做一些很酷的事情。&lt;/p&gt;
&lt;p&gt;选择慢、深和困难，而不是快速、浅和容易。最典型的例子是读书与刷抖音。这个模板可以应用于各种各样的事情。你可以非常清楚地衡量你在康复道路上的道路，选择缓慢、深入和困难的难度。当它成为您毫不费力的偏好时，您就自由了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;追求创意领域。写字、做音乐、学习技能、画画或发展你的书法、学习编程。&lt;/li&gt;
&lt;li&gt;保留有趣的项目想法列表。当你需要做点什么时，回到他们身边，挑选一些东西去做。&lt;/li&gt;
&lt;li&gt;加入读书俱乐部、语言学习小组、远足小组、写作小组、戏剧小组、攀岩馆、运动队、社区志愿者小组、当地创客空间。&lt;/li&gt;
&lt;li&gt;学习正规的高中或大学水平的东西来填补空白 —— 物理、历史、数学、地理、社会学。在线学习资源比以往任何时候都好。&lt;/li&gt;
&lt;li&gt;去享受美妙的体验吧。在节日上跳舞，远足，露营，探索（你不需要机票 - 在当地探索！），并培养与周围世界的互动感。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="观念就是一切"&gt;&lt;a href="#%e8%a7%82%e5%bf%b5%e5%b0%b1%e6%98%af%e4%b8%80%e5%88%87" class="header-anchor"&gt;&lt;/a&gt;观念就是一切
&lt;/h2&gt;&lt;p&gt;乐观主义是对人类心智最有力的激励因素。培育它是一门微妙的艺术，但一旦它开始燃烧，它将以难以置信方式激励你。相信积极的结果可以并且确实会发生，它值得努力追求，它使得人类的经历充满了色彩、可能性和魔力。它还创造了一个积极的反馈循环，这些结果实际上更频繁地发生，因为你已经将它们纳入了你的世界观。&lt;/p&gt;</description></item><item><title>过去 66 年的 66 项最佳年度发明</title><link>https://xiaobox.github.io/p/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/</link><pubDate>Fri, 26 Jan 2024 04:31:57 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/cover.jpg" alt="Featured image of post 过去 66 年的 66 项最佳年度发明" /&gt;
 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;从 20 世纪 50 年代至今，科学技术创新彻底改变了我们的生活，从医院到外太空再到厨房。这些是我们这个时代最有影响力的发明。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;在一个寻常的日子里，你可能会系上安全带、从 ATM 机取现、或者在手机上查看新闻。这些事情感觉起来很平常，然而在不久的过去，它们都是不可思议的，这都要感谢超过六十五年的卓越科学和技术创新。从魔术贴到虚拟现实，从 LED 灯到 微信，以下这些都是我们这个时代最能改变生活、最有名的发明。&lt;/p&gt;
&lt;h2 id="1954-年微波炉"&gt;&lt;a href="#1954-%e5%b9%b4%e5%be%ae%e6%b3%a2%e7%82%89" class="header-anchor"&gt;&lt;/a&gt;1954 年：微波炉
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/001-84f7ca29.png"&gt;&lt;/p&gt;
&lt;p&gt;1945年，雷神公司的 Percy Spencer 站在一个磁控管（雷达的功率管）前，感觉到口袋里的糖果开始融化：他觉得很有趣。当他把爆米花粒放在磁控管前时，粒子在实验室里到处爆炸。十年后，Spencer 为一种使用高频射频波进行烹饪的&amp;quot;雷达烘箱&amp;quot;申请了专利；同年，Tappan炉具公司推出了第一款家用微波炉模型。&lt;/p&gt;
&lt;h2 id="1955-年脊髓灰质炎疫苗"&gt;&lt;a href="#1955-%e5%b9%b4%e8%84%8a%e9%ab%93%e7%81%b0%e8%b4%a8%e7%82%8e%e7%96%ab%e8%8b%97" class="header-anchor"&gt;&lt;/a&gt;1955 年：脊髓灰质炎疫苗
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/002-34a3aeb7.png"&gt;&lt;/p&gt;
&lt;p&gt;乔纳斯·索尔克 (Jonas Salk) 找到预防脊髓灰质炎方法的那一年，全球已有 28,985 例病例；到 2021 年，这个数字将下降到 6 个。&lt;/p&gt;
&lt;h2 id="1956-年硬盘"&gt;&lt;a href="#1956-%e5%b9%b4%e7%a1%ac%e7%9b%98" class="header-anchor"&gt;&lt;/a&gt;1956 年：硬盘
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/003-1c304218.png"&gt;&lt;/p&gt;
&lt;p&gt;IBM 发布了第一款计算机硬盘驱动器，这是一个重达 2000 磅以上，冰箱大小的 IBM 305 RAMAC，它引入了磁盘存储。在此之前，文件要么保存在磁带卷上，要么就是老式的纸张上，无法直接跳转到你想要查看的记录。有了 RAMAC，一个机械臂可以通过在特定的磁向存储数据来检索数据。这项技术后来被用于（尺寸更小的）笔记本电脑和计算机服务器。&lt;/p&gt;
&lt;h2 id="1957-年避孕药"&gt;&lt;a href="#1957-%e5%b9%b4%e9%81%bf%e5%ad%95%e8%8d%af" class="header-anchor"&gt;&lt;/a&gt;1957 年：避孕药
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/004-e5d2ccf2.png"&gt;&lt;/p&gt;
&lt;p&gt;Enovid 是 FDA 批准用于治疗月经失调的药物，它附带一个警告：合成黄体酮和雌激素的混合物也会阻止排卵。两年后，超过 50 万美国女性正在服用 Enovid，但并非所有人都出现抽筋症状。1960 年，FDA 批准 Enovid 作为第一种口服避孕药。&lt;/p&gt;
&lt;h2 id="1958-年喷气式客机"&gt;&lt;a href="#1958-%e5%b9%b4%e5%96%b7%e6%b0%94%e5%bc%8f%e5%ae%a2%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;1958 年：喷气式客机
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/005-e1c665aa.png"&gt;&lt;/p&gt;
&lt;p&gt;波音 707-120 首次亮相，成为世界上首款成功的商用喷气式客机，开启了便捷大众航空旅行的时代。这架四引擎飞机可搭载 181 名乘客，满油情况下最高时速可达 600 英里，续航里程高达 5280 英里。首次商业喷气式飞行从纽约起飞，降落在巴黎；很快，国内航线开始连接纽约和洛杉矶。&lt;/p&gt;
&lt;h2 id="1959集成电路"&gt;&lt;a href="#1959%e9%9b%86%e6%88%90%e7%94%b5%e8%b7%af" class="header-anchor"&gt;&lt;/a&gt;1959：集成电路
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/006-e7159aa1.png"&gt;&lt;/p&gt;
&lt;p&gt;第一台通用计算机是近 30 吨重的 ENIAC（1947 年），包含 18,000 个真空管、70,000 个电阻器和 10,000 个电容器。1959 年，集成电路将这些内部结构集成到一个微小的芯片上。&lt;/p&gt;
&lt;h2 id="1960起搏器"&gt;&lt;a href="#1960%e8%b5%b7%e6%90%8f%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;1960：起搏器
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/007-9af3e0a6.png"&gt;&lt;/p&gt;
&lt;p&gt;1956 年，威尔逊·格莱特巴奇 (Wilson Greatbatch) 抓住了错误的电阻，并将其连接到他正在建造的用于记录心跳的设备上。当电路发出脉冲时，他意识到该装置可以用来控制节拍；1960年，第一台起搏器成功植入人体&lt;/p&gt;
&lt;h2 id="1961-年无绳电钻"&gt;&lt;a href="#1961-%e5%b9%b4%e6%97%a0%e7%bb%b3%e7%94%b5%e9%92%bb" class="header-anchor"&gt;&lt;/a&gt;1961 年：无绳电钻
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/008-7103bdfb.png"&gt;&lt;/p&gt;
&lt;p&gt;Black and Decker 发布了首款无绳电钻，但设计人员无法从其 NiCd 电池中获得超过 20 瓦的功率。相反，他们努力提高效率，修改齿轮比并使用更好的材料。这一革命性成果为 DIY 爱好者以及宇航员的手套（得益于 NASA 合同）带来了新的力量。&lt;/p&gt;
&lt;h2 id="1962-通讯卫星"&gt;&lt;a href="#1962-%e9%80%9a%e8%ae%af%e5%8d%ab%e6%98%9f" class="header-anchor"&gt;&lt;/a&gt;1962: 通讯卫星
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/009-841d098a.png"&gt;&lt;/p&gt;
&lt;p&gt;Telstar 作为第一颗“主动”通信卫星发射——主动放大和转发传入信号，而不是被动地将信号反射回地球。Telstar 将科幻作家 Arthur C. Clarke 于 1945 年提出的构想变为现实，他设想了一个基于地球同步卫星的全球通信网络。泰事达首次亮相两周后，肯尼迪总统在华盛顿特区举行新闻发布会，并在大西洋彼岸进行现场直播。&lt;/p&gt;
&lt;h2 id="1963画板程序"&gt;&lt;a href="#1963%e7%94%bb%e6%9d%bf%e7%a8%8b%e5%ba%8f" class="header-anchor"&gt;&lt;/a&gt;1963：画板程序
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/010-166e3c73.png"&gt;&lt;/p&gt;
&lt;p&gt;计算机图形学之父 Ivan Sutherland 在创建 Sketchpad 程序时彻底改变了 3D 计算机建模和模拟。作为计算机辅助设计 (CAD) 程序的最早迭代，画板率先使用了几何约束（固定直线的长度或两段之间的角度）。它也是最早使用图形用户界面（而不是基于文本的用户界面）的程序之一&lt;/p&gt;
&lt;h2 id="1964-年无人机"&gt;&lt;a href="#1964-%e5%b9%b4%e6%97%a0%e4%ba%ba%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;1964 年：无人机
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/011-6adf6272.png"&gt;&lt;/p&gt;
&lt;p&gt;遥控飞机的广泛使用始于越南战争期间，部署了 1000 架 AQM-34 Ryan Firebees。这些长 29 英尺的飞机的第一架模型于 1962 年在短短 90 天内开发完成。AQM-34 执行了超过 34,000 次监视任务。他们的成功导致了当今广泛使用的无人机的最终发展。&lt;/p&gt;
&lt;h2 id="1965凯夫拉纤维"&gt;&lt;a href="#1965%e5%87%af%e5%a4%ab%e6%8b%89%e7%ba%a4%e7%bb%b4" class="header-anchor"&gt;&lt;/a&gt;1965：凯夫拉纤维
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/012-0abda736.png"&gt;&lt;/p&gt;
&lt;p&gt;感谢杜邦公司的 Stephanie Kwolek 和 Herbert Blades 在 1965 年发明了一种名为 KEVLAR 的高强度聚合物，3000 多名警察的防弹衣保护了他们免受致命攻击。&lt;/p&gt;
&lt;h2 id="1966年高产水稻"&gt;&lt;a href="#1966%e5%b9%b4%e9%ab%98%e4%ba%a7%e6%b0%b4%e7%a8%bb" class="header-anchor"&gt;&lt;/a&gt;1966年：高产水稻
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/013-ba9acc4f.png"&gt;&lt;/p&gt;
&lt;p&gt;菲律宾国际水稻研究所推出了一种半矮化高产籼稻品种，与高产小麦相结合，引领了绿色革命。籼稻在亚洲和南美洲的热带地区蓬勃发展，到 1970 年全球产量提高了 20% 以上。&lt;/p&gt;
&lt;h2 id="1967-年冠状动脉搭桥手术"&gt;&lt;a href="#1967-%e5%b9%b4%e5%86%a0%e7%8a%b6%e5%8a%a8%e8%84%89%e6%90%ad%e6%a1%a5%e6%89%8b%e6%9c%af" class="header-anchor"&gt;&lt;/a&gt;1967 年：冠状动脉搭桥手术
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/014-fa5b6ca5.png"&gt;&lt;/p&gt;
&lt;p&gt;1967 年，雷内·法瓦洛罗 (Rene Favaloro) 进行了首例冠状动脉搭桥手术，从腿部取出一段静脉并将其移植到冠状动脉上。这使得血液可以在阻塞部分周围流动。部分归功于这些进步，美国因心脏病死亡的人数下降了近 50%。&lt;/p&gt;
&lt;h2 id="1968-集成计算机系统"&gt;&lt;a href="#1968-%e9%9b%86%e6%88%90%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;1968: 集成计算机系统
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/015-821b6eba.png"&gt;&lt;/p&gt;
&lt;p&gt;在 1968 年 12 月具有里程碑意义的演示（后来被称为所有演示之母）中，工程师道格拉斯·恩格尔巴特 (Douglas Engelbart) 演示了许多最新技术的相互结合使用，包括：屏幕窗口、超文本、图形、文件链接、版本控制、视频会议、电脑鼠标和文字处理。Mac 和 Windows 用户界面都将大量借鉴此处设置的示例。&lt;/p&gt;
&lt;h2 id="1969阿帕网"&gt;&lt;a href="#1969%e9%98%bf%e5%b8%95%e7%bd%91" class="header-anchor"&gt;&lt;/a&gt;1969：阿帕网
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/016-aa41fc0e.png"&gt;&lt;/p&gt;
&lt;p&gt;在整个世界联网之前，就有了阿帕网——1969 年将四台计算机连接起来。它引入了“数据包交换”的概念，即同时将消息作为短单元传送，并在目的地重新组装它们。&lt;/p&gt;
&lt;h2 id="1970-年光纤"&gt;&lt;a href="#1970-%e5%b9%b4%e5%85%89%e7%ba%a4" class="header-anchor"&gt;&lt;/a&gt;1970 年：光纤
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/017-c37393d5.png"&gt;&lt;/p&gt;
&lt;p&gt;“光纤”一词于 1956 年创造，但直到 1970 年，康宁公司的科学家才生产出一种超纯玻璃光纤，其光传输性能足以用于电信。&lt;/p&gt;
&lt;h2 id="1971-年华夫格底跑鞋"&gt;&lt;a href="#1971-%e5%b9%b4%e5%8d%8e%e5%a4%ab%e6%a0%bc%e5%ba%95%e8%b7%91%e9%9e%8b" class="header-anchor"&gt;&lt;/a&gt;1971 年：华夫格底跑鞋
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/018-9260ddfe.png"&gt;&lt;/p&gt;
&lt;p&gt;俄勒冈大学的田径教练比尔·鲍尔曼（Bill Bowerman）为了达到最佳表现而牺牲了早餐，他将橡胶倒入华夫饼熨斗中，为运动员的跑鞋制作轻质鞋底。三年后，鲍尔曼的公司 Nike 推出了 Waffle Trainer，一经推出就大受欢迎。&lt;/p&gt;
&lt;h2 id="1972-年电子点火"&gt;&lt;a href="#1972-%e5%b9%b4%e7%94%b5%e5%ad%90%e7%82%b9%e7%81%ab" class="header-anchor"&gt;&lt;/a&gt;1972 年：电子点火
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/019-36610345.png"&gt;&lt;/p&gt;
&lt;p&gt;克莱斯勒通过电子点火为汽车的电子化（而非机械化）时代铺平了道路。它导致了点火正时和燃油计量的电子控制，预示着更复杂的系统即将到来。如今，这些技术包括电子控制变速箱换档点、防抱死制动系统、牵引力控制系统、转向系统和安全气囊部署。&lt;/p&gt;
&lt;h2 id="1973核磁共振成像"&gt;&lt;a href="#1973%e6%a0%b8%e7%a3%81%e5%85%b1%e6%8c%af%e6%88%90%e5%83%8f" class="header-anchor"&gt;&lt;/a&gt;1973：核磁共振成像
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/020-582d6faf.png"&gt;&lt;/p&gt;
&lt;p&gt;每个人都同意磁共振成像 (MRI) 是一项辉煌的发明，但对于谁发明了它却没有人达成一致。MRI 所依赖的物理效应（核磁共振）为多位科学家赢得了 1944 年和 1952 年的诺贝尔物理学奖。许多人认为，雷蒙德·达马迪安 (Raymond Damadian) 于 1973 年首次使用磁共振来区分健康组织和癌症，从而确立了该机器的医学价值。然而，2003 年，诺贝尔医学奖颁给了彼得·劳特伯 (Peter Lauterbur) 和彼得·曼斯菲尔德 (Peter Mansfield)，以表彰他们的“开创性发现”。谁是最有价值的候选人这一话题仍然存在激烈争论。&lt;/p&gt;
&lt;h2 id="1974-条形码"&gt;&lt;a href="#1974-%e6%9d%a1%e5%bd%a2%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;1974: 条形码
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/021-59e5cdf0.png"&gt;&lt;/p&gt;
&lt;p&gt;10 包箭牌 Juicy Fruit 口香糖是第一个在俄亥俄州杂货店扫描时集成条形码技术的产品；这些代码成为杂货店存储定价信息的行业标准，并迅速扩展到面向消费者和内部跟踪应用程序。&lt;/p&gt;
&lt;h2 id="1975-年全球变暖"&gt;&lt;a href="#1975-%e5%b9%b4%e5%85%a8%e7%90%83%e5%8f%98%e6%9a%96" class="header-anchor"&gt;&lt;/a&gt;1975 年：全球变暖
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/022-a2ab8e93.png"&gt;&lt;/p&gt;
&lt;p&gt;不是发明的，而是以现代意义上的人为气候变化引入词汇的。《科学》杂志发表了地球科学家华莱士·布罗克 (Wallace Broecker) 的一篇论文，“我们正处于明显的全球变暖的边缘吗？”——这标志着该短语首次在科学论文中使用。&lt;/p&gt;
&lt;h2 id="1976-超级计算机"&gt;&lt;a href="#1976-%e8%b6%85%e7%ba%a7%e8%ae%a1%e7%ae%97%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;1976: 超级计算机
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/023-292bcad5.png"&gt;&lt;/p&gt;
&lt;p&gt;Cray-1 是第一台商业开发的超级计算机，安装在洛斯阿拉莫斯国家实验室。它是第一台成功实现矢量处理器的超级计算机，该系统允许对大量数据快速执行单个操作，这反映在其 160 MFLOPS 或每秒 1.6 亿次浮点运算的速度上。Summit 超级计算机于 2018 年在橡树岭国家实验室上线，运算能力为 143.5 petaflops。&lt;/p&gt;
&lt;h2 id="1977-个人电脑"&gt;&lt;a href="#1977-%e4%b8%aa%e4%ba%ba%e7%94%b5%e8%84%91" class="header-anchor"&gt;&lt;/a&gt;1977: 个人电脑
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/024-396e465e.png"&gt;&lt;/p&gt;
&lt;p&gt;Apple II、Commodore PET 和 Radio Shack 的 TRS-80 于 1977 年推出——比 IBM 推出其个人电脑早了四年，IBM 很快就成为“PC”一词的代名词。&lt;/p&gt;
&lt;h2 id="1978-年全球定位系统"&gt;&lt;a href="#1978-%e5%b9%b4%e5%85%a8%e7%90%83%e5%ae%9a%e4%bd%8d%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;1978 年：全球定位系统
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/025-d52921ca.png"&gt;&lt;/p&gt;
&lt;p&gt;现代 Navstar 全球定位系统 (GPS) 中的第一颗卫星发射升空。（GPS 的前身 TRANSIT 于 20 世纪 60 年代初开发，用于引导核潜艇。）不过，直到 2000 年，克林顿总统才允许非军事用户访问未加密的 GPS 信号。现在，廉价的手持式 GPS 设备可以确定一个人的位置，精确度在 3 码以内。&lt;/p&gt;
&lt;h2 id="1979-年索尼随身听"&gt;&lt;a href="#1979-%e5%b9%b4%e7%b4%a2%e5%b0%bc%e9%9a%8f%e8%ba%ab%e5%90%ac" class="header-anchor"&gt;&lt;/a&gt;1979 年：索尼随身听
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/026-96d19a72.png"&gt;&lt;/p&gt;
&lt;p&gt;“这是一款能够满足那些想要整天听音乐的年轻人的产品。” ——盛田昭夫，索尼董事长，1979 年 2 月。&lt;/p&gt;
&lt;h2 id="1980-年氧化钴阴极"&gt;&lt;a href="#1980-%e5%b9%b4%e6%b0%a7%e5%8c%96%e9%92%b4%e9%98%b4%e6%9e%81" class="header-anchor"&gt;&lt;/a&gt;1980 年：氧化钴阴极
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/027-6c251294.png"&gt;&lt;/p&gt;
&lt;p&gt;约翰·班尼斯特·古迪纳夫 (John Bannister Goodenough) 发明了氧化钴阴极，这是锂离子电池的重要组成部分，锂离子电池是现在每部智能手机、笔记本电脑和电动汽车中都配备的可充电便携式电池。2017 年，94 岁的古迪纳夫（显然认为他的上一项发明不够好）宣布他发明了一种具有更好存储能力的新型玻璃电池。&lt;/p&gt;
&lt;h2 id="1981扫描隧道显微镜"&gt;&lt;a href="#1981%e6%89%ab%e6%8f%8f%e9%9a%a7%e9%81%93%e6%98%be%e5%be%ae%e9%95%9c" class="header-anchor"&gt;&lt;/a&gt;1981：扫描隧道显微镜
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/028-83f6373a.png"&gt;&lt;/p&gt;
&lt;p&gt;通过在表面上移动扫描隧道显微镜 (STM) 的针并监测流过它的电流，科学家可以将表面映射到单个原子的水平。STM 非常精确，它不仅可以观察原子，还可以将它们操纵成结构。该显微镜的开发为 IBM 研究人员 Gerd Binnig 和 Heinrich Rohrer 赢得了诺贝尔奖，并帮助开启了纳米技术的新兴时代。&lt;/p&gt;
&lt;h2 id="1982计算机病毒"&gt;&lt;a href="#1982%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%97%85%e6%af%92" class="header-anchor"&gt;&lt;/a&gt;1982：计算机病毒
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/029-2a7fb951.png"&gt;&lt;/p&gt;
&lt;p&gt;15 岁的 Rich Skrenta 创建了一个名为 Elk Cloner 的应用程序作为恶作剧，并最终创建了第一个在其家庭网络之外传播的病毒。Elk Cloner 通过软盘传播并附加到 Apple OS II 操作系统。当用户从磁盘启动时，Elk Cloner 会传输计算机的内存；任何未重新启动而插入的其他磁盘也会受到感染。每启动五十次，计算机就会显示 Skrenta 编写的文本：&lt;/p&gt;
&lt;h2 id="1983-年微软-word"&gt;&lt;a href="#1983-%e5%b9%b4%e5%be%ae%e8%bd%af-word" class="header-anchor"&gt;&lt;/a&gt;1983 年：微软 Word
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/030-4cb56020.png"&gt;&lt;/p&gt;
&lt;p&gt;Multi-Tool Word（Microsoft Word 文本编辑程序的前身）首次亮相，免费版与 11 月号《PC World》捆绑在一起。与大多数当代竞争对手不同，Word 被设计为通过鼠标使用，并且具有撤消键入以及显示粗体、斜体和下划线文本的功能。&lt;/p&gt;
&lt;h2 id="1984dna-指纹识别"&gt;&lt;a href="#1984dna-%e6%8c%87%e7%ba%b9%e8%af%86%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;1984：DNA 指纹识别
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/031-40905402.png"&gt;&lt;/p&gt;
&lt;p&gt;分子生物学家 Alec Jeffreys 设计了一种方法，通过仅比较显示人与人之间差异最大的序列部分，使对人类 DNA 序列中超过 30 亿个单位的分析变得更加容易。他的方法很快就进入了法庭，用来为被错误指控的人开脱罪责，并找出真正的罪犯。&lt;/p&gt;
&lt;h2 id="1985聚合酶链式反应"&gt;&lt;a href="#1985%e8%81%9a%e5%90%88%e9%85%b6%e9%93%be%e5%bc%8f%e5%8f%8d%e5%ba%94" class="header-anchor"&gt;&lt;/a&gt;1985：聚合酶链式反应
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/032-87c38802.png"&gt;&lt;/p&gt;
&lt;p&gt;生物化学家 Kary Mullis 发明了一种利用酶的技术，可以快速、廉价地复制微小的 DNA 片段，复制数百万份。无论血迹有多小或多干，法医科学家现在都可以收集足够的遗传物质来进行 DNA 指纹识别。通过 PCR，医生还可以搜索微量的 HIV 遗传密码，从而比传统方法更快地诊断感染。&lt;/p&gt;
&lt;h2 id="1986电子邮件列表"&gt;&lt;a href="#1986%e7%94%b5%e5%ad%90%e9%82%ae%e4%bb%b6%e5%88%97%e8%a1%a8" class="header-anchor"&gt;&lt;/a&gt;1986：电子邮件列表
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/033-96189a7f.png"&gt;&lt;/p&gt;
&lt;p&gt;Éric Thomas 开发了 LISTSERV，这是第一个自动化邮件列表管理应用程序。1986 年之前，必须手动在邮件列表中添加或删除人员。到了 2010 年代，电子邮件通讯已经无处不在。&lt;/p&gt;
&lt;h2 id="1987百忧解"&gt;&lt;a href="#1987%e7%99%be%e5%bf%a7%e8%a7%a3" class="header-anchor"&gt;&lt;/a&gt;1987：百忧解
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/034-d542d92b.png"&gt;&lt;/p&gt;
&lt;p&gt;百忧解成为 FDA 批准的新型抗抑郁药中的第一个，称为“选择性血清素再摄取抑制剂”，它可以阻止提升情绪的神经递质血清素的重吸收，从而延长其作用。尽管有时存在争议，但百忧解可以帮助患者应对临床抑郁症，重塑我们对如何通过化学方法控制性格和情绪的理解。五年内，450 万美国人服用百忧解，使其成为有史以来最广泛接受的精神药物。&lt;/p&gt;
&lt;h2 id="1988网络病毒"&gt;&lt;a href="#1988%e7%bd%91%e7%bb%9c%e7%97%85%e6%af%92" class="header-anchor"&gt;&lt;/a&gt;1988：网络病毒
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/035-f6c75910.png"&gt;&lt;/p&gt;
&lt;p&gt;研究生 Robert Morris 于 11 月 2 日发布了名为 Morris 蠕虫病毒的病毒，展示了远程连接计算机中的漏洞。与 Rich Skrenta 的 Elk Cloner 不同，该蠕虫病毒不需要任何类型的硬件来进行传输。&lt;/p&gt;
&lt;p&gt;虽然莫里斯说这只是衡量互联网规模的一个练习，但多次被感染的计算机速度会大大减慢；在最初的 15 小时内，就有 2,000 台计算机被感染，其中许多计算机无法挽救。莫里斯成为第一个根据 1984 年《计算机欺诈和滥用法》受到审判并被定罪的人。&lt;/p&gt;
&lt;h2 id="1989万维网"&gt;&lt;a href="#1989%e4%b8%87%e7%bb%b4%e7%bd%91" class="header-anchor"&gt;&lt;/a&gt;1989：万维网
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/036-b2def0f3.png"&gt;&lt;/p&gt;
&lt;p&gt;1989 年，蒂姆·伯纳斯·李爵士创建了用于制作网页的“超文本标记语言”(HTML) 和用于标识信息存储位置的“统一资源定位符”(URL)。这些突破构成了万维网的基础。&lt;/p&gt;
&lt;h2 id="1990photoshop"&gt;&lt;a href="#1990photoshop" class="header-anchor"&gt;&lt;/a&gt;1990：Photoshop
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/037-ecb6db96.png"&gt;&lt;/p&gt;
&lt;p&gt;如今，有数以千计的应用程序让我们的数字生活变得更加轻松，但没有一个像 Photoshop 那样有用。这款广受欢迎的照片编辑软件于 1987 年首次开发，直到 1990 年才发布其第一个商业版本。这款应用程序在我们所有设备上仍然无处不在，这是有原因的——它就是那么好。&lt;/p&gt;
&lt;h2 id="1991linux"&gt;&lt;a href="#1991linux" class="header-anchor"&gt;&lt;/a&gt;1991：Linux
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/038-9afd0720.png"&gt;&lt;/p&gt;
&lt;p&gt;在微软和苹果主导的早期网络世界中，Linux 是一个新的、强大的想法。该操作系统（包括 Linux 内核）最初由 Linus Torvalds 于 1991 年 9 月 17 日发布，成为开源软件最重要的示例之一。现在，Linux 有了各种不同的发行版，为我们提供了一种逃离日益掌控我们生活的科技公司的数字逃离方式。&lt;/p&gt;
&lt;h2 id="1992ibm-西蒙"&gt;&lt;a href="#1992ibm-%e8%a5%bf%e8%92%99" class="header-anchor"&gt;&lt;/a&gt;1992：IBM 西蒙
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/039-d78233aa.png"&gt;&lt;/p&gt;
&lt;p&gt;1992 年 11 月 23 日，IBM 在内华达州拉斯维加斯的 COMDEX 上首次展示了一款奇怪的小原型。尽管 IBM Simon 直到 1994 年才在美国销售，但事实证明它在商业上失败了。但实际上，这个想法远远超前于时代，因为许多人认为 Simon 是世界上第一款智能手机。&lt;/p&gt;
&lt;h2 id="1993-年燃料电池汽车"&gt;&lt;a href="#1993-%e5%b9%b4%e7%87%83%e6%96%99%e7%94%b5%e6%b1%a0%e6%b1%bd%e8%bd%a6" class="header-anchor"&gt;&lt;/a&gt;1993 年：燃料电池汽车
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/040-4c2730b1.png"&gt;&lt;/p&gt;
&lt;p&gt;燃料电池的历史可以追溯到 150 多年前，第一辆燃料电池汽车（20 马力拖拉机）于 1959 年制造。但直到 1993 年，加拿大公司 Ballard Power Systems 才首次展示了零排放燃料电池公交车。从那时起，经济上可行的燃料电池汽车的进展仍然缓慢但稳定。&lt;/p&gt;
&lt;h2 id="1994-年rq-1-捕食者无人机"&gt;&lt;a href="#1994-%e5%b9%b4rq-1-%e6%8d%95%e9%a3%9f%e8%80%85%e6%97%a0%e4%ba%ba%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;1994 年：RQ-1 捕食者无人机
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/041-c531d4ba.png"&gt;&lt;/p&gt;
&lt;p&gt;RQ-1“捕食者”无人机的想法诞生于 20 世纪 80 年代，但直到 1994 年才在莫哈韦沙漠进行了首次飞行测试。从那时起，无人机越来越多地融入美国军队，并永远改变了人类的战争方式。2002年，该无人机获得了“MQ”称号，代表“多角色”，以表明其武装能力超出了被动侦察的范围。&lt;/p&gt;
&lt;p&gt;这是机器代替人类进行战争的首批实例之一。批评者称，“捕食者”无人机因错误的情报造成无辜者死亡和附带损害，而支持者则表示，与平均脱靶距离为 800 英尺的传统火炮武器相比，无人机的精确度要高得多。&lt;/p&gt;
&lt;p&gt;但在战场之外，“捕食者”无人机也为其他类型的无人机机器人的功能提供了令人印象深刻的例子，一些专家表示，正是它引发了我们目前对无人机的迷恋，无论是用于运送包裹还是作为一种新的最受欢迎的消遣。在很多方面，《铁血战士》对我们生活的影响尚未得到充分认识。&lt;/p&gt;
&lt;h2 id="1995-年hiv-蛋白酶抑制剂"&gt;&lt;a href="#1995-%e5%b9%b4hiv-%e8%9b%8b%e7%99%bd%e9%85%b6%e6%8a%91%e5%88%b6%e5%89%82" class="header-anchor"&gt;&lt;/a&gt;1995 年：HIV 蛋白酶抑制剂
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/042-d56606c5.png"&gt;&lt;/p&gt;
&lt;p&gt;艾滋病毒感染者的前景也发生了巨大变化。FDA 于 1995 年批准了 Invirase，它是 HIV 蛋白酶抑制剂类药物中的第一种药物。通过阻断病毒复制中使用的酶的功能，这些抑制剂可以将高达 90% 的患者的 HIV 水平持续降低到不可检测的水平。&lt;/p&gt;
&lt;h2 id="1996dvd"&gt;&lt;a href="#1996dvd" class="header-anchor"&gt;&lt;/a&gt;1996：DVD
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/043-95b17551.png"&gt;&lt;/p&gt;
&lt;p&gt;尽管 DVD 仅通过其祖先蓝光（一种逐渐被在线流媒体消耗的技术）得以延续至今，但由于与其他媒体相比，DVD 的容量较高，因此作为家庭娱乐和数据存储的首选媒体，DVD 已向前迈出了一大步。格式。第一批 DVD 播放机于 1996 年 11 月 1 日在日本上市。&lt;/p&gt;
&lt;h2 id="1997混合动力汽车"&gt;&lt;a href="#1997%e6%b7%b7%e5%90%88%e5%8a%a8%e5%8a%9b%e6%b1%bd%e8%bd%a6" class="header-anchor"&gt;&lt;/a&gt;1997：混合动力汽车
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/044-b9155605.png"&gt;&lt;/p&gt;
&lt;p&gt;费迪南德·保时捷 (Ferdinand Porsche) 驾驶前轮驱动混合动力汽车在 1902 年奥地利埃克塞尔伯格爬坡赛中赢得了组别冠军。但近一个世纪后的 1997 年，丰田向日本消费者推出了混合动力普锐斯，令其竞争对手大吃一惊。普锐斯花了近三年时间才到达北美。&lt;/p&gt;
&lt;h2 id="1998国际空间站"&gt;&lt;a href="#1998%e5%9b%bd%e9%99%85%e7%a9%ba%e9%97%b4%e7%ab%99" class="header-anchor"&gt;&lt;/a&gt;1998：国际空间站
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/045-ab8493b0.png"&gt;&lt;/p&gt;
&lt;p&gt;1998 年 11 月 20 日，功能货物舱（又名查莉娅）发射升空，成为最终成为国际空间站的第一部分。国际空间站是无数实验的所在地，也是国际合作的光辉典范，它证明了人类通过共同努力可以取得的成就。&lt;/p&gt;
&lt;h2 id="1999-年蓝牙-10-版"&gt;&lt;a href="#1999-%e5%b9%b4%e8%93%9d%e7%89%99-10-%e7%89%88" class="header-anchor"&gt;&lt;/a&gt;1999 年：蓝牙 1.0 版
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/046-067d4e56.png"&gt;&lt;/p&gt;
&lt;p&gt;蓝牙以 10 世纪丹麦国王哈拉尔·“蓝牙”·戈姆森（Harald“Bluetooth”Gormsson）的名字命名（真的），现在我们几乎可以在所有可以想象到的小工具中找到蓝牙，并且它将成为智能手机未来发展的主要参与者。蓝牙的第一个版本于 1999 年 7 月 26 日发布，虽然需要十年（或两年）的时间才能解决这些问题，但它帮助我们想象了一个没有不必要电线的未来。&lt;/p&gt;
&lt;h2 id="2000-年playstation-2"&gt;&lt;a href="#2000-%e5%b9%b4playstation-2" class="header-anchor"&gt;&lt;/a&gt;2000 年：PlayStation 2
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/047-3438cc5f.png"&gt;&lt;/p&gt;
&lt;p&gt;从长远来看，视频游戏不一定是重要的发明，但它们很有趣。虽然许多游戏机都可以跻身这份名单，但索尼的 PlayStation 2 利用新兴技术时代创造了一款游戏机，巩固了该公司作为游戏巨头的地位，这一头衔至今仍被保留。&lt;/p&gt;
&lt;h2 id="2001维基百科"&gt;&lt;a href="#2001%e7%bb%b4%e5%9f%ba%e7%99%be%e7%a7%91" class="header-anchor"&gt;&lt;/a&gt;2001：维基百科
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/048-34b67439.png"&gt;&lt;/p&gt;
&lt;p&gt;事后看来，将百科全书放到网上是理所当然的。但是，数字百科全书在近二十年的时间里都没有广告，这真是令人难以置信。维基百科的用户生成模型有时会给它带来麻烦，但总的来说，它是一个成为在线寻找答案的基石的程序，如果幸运的话，它将在未来几十年内继续这样做。&lt;/p&gt;
&lt;h2 id="2002ieee-80216"&gt;&lt;a href="#2002ieee-80216" class="header-anchor"&gt;&lt;/a&gt;2002：IEEE 802.16
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/049-91fecc31.png"&gt;&lt;/p&gt;
&lt;p&gt;电气和电子工程师协会的天才们发布了无线城域网标准，其功能就像增强版的 Wi-Fi。802.16 天线可以将互联网接入传输到半径达 30 英里的范围内，速度与 DSL 和有线宽带相当。当一切尘埃落定后，802.16 可能会消除对有线电信基础设施的需求，从而最终将发展中国家带入数字时代。&lt;/p&gt;
&lt;h2 id="2003-年人类基因组计划"&gt;&lt;a href="#2003-%e5%b9%b4%e4%ba%ba%e7%b1%bb%e5%9f%ba%e5%9b%a0%e7%bb%84%e8%ae%a1%e5%88%92" class="header-anchor"&gt;&lt;/a&gt;2003 年：人类基因组计划
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/050-b70aef32.png"&gt;&lt;/p&gt;
&lt;p&gt;人类基因组计划于 2003 年 4 月 14 日正式完成，为未来医学的进一步发展和更好地理解我们来自何处奠定了理解基础。事实上，每个人都可以在线使用它，这一事实让它变得更加令人难以置信。&lt;/p&gt;
&lt;h2 id="2004-年脸书"&gt;&lt;a href="#2004-%e5%b9%b4%e8%84%b8%e4%b9%a6" class="header-anchor"&gt;&lt;/a&gt;2004 年：脸书
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/051-79cac70e.png"&gt;&lt;/p&gt;
&lt;p&gt;未来的哈佛辍学者马克·扎克伯格 (Mark Zuckerberg) 于 2004 年 2 月推出了“thefacebook.com”，这是一个最初仅限他的同学使用的社交网站。到其 10 周年纪念日时，Facebook 平均每月有 12.3 亿用户——占全球总人口的 17%。2018 年，扎克伯格被要求在美国国会作证，说明从该网站窃取的个人数据和定向 Facebook 广告是如何被利用来干扰 2016 年总统选举的。&lt;/p&gt;
&lt;h2 id="2005-年谷歌地图"&gt;&lt;a href="#2005-%e5%b9%b4%e8%b0%b7%e6%ad%8c%e5%9c%b0%e5%9b%be" class="header-anchor"&gt;&lt;/a&gt;2005 年：谷歌地图
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/052-e719eb78.png"&gt;&lt;/p&gt;
&lt;p&gt;谷歌地图将动态的、可搜索的在线地图与生成路线规划驾驶指令的能力相结合，对停车和问路带来了决定性的打击。两年后，谷歌增加了街景功能，向世界各地发送汽车、徒步旅行者和机器人，努力让用户看到房屋、道路和地标的 360 度街道视图。第一代 iPhone 中还包含了谷歌地图的应用程序版本——据报道，蒂姆·库克 (Tim Cook) 在发布前几周就委托了这款应用程序，当时他意识到苹果原型机无法满足这一需求。&lt;/p&gt;
&lt;h2 id="2006wii"&gt;&lt;a href="#2006wii" class="header-anchor"&gt;&lt;/a&gt;2006：Wii
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/053-23d0a9df.png"&gt;&lt;/p&gt;
&lt;p&gt;任天堂于 2006 年 11 月发布了 Wii 的标志性产品 Wii Remote，它使用光学传感器和手势识别来反映玩家在游戏范围内的真实动作，从网球到马里奥赛车。无论你的父母怎么说，它都比前几代视频游戏更具沉浸感，对体力要求更高，并且是综合现实世界和虚拟活动的重要一步。&lt;/p&gt;
&lt;h2 id="2007-年iphone"&gt;&lt;a href="#2007-%e5%b9%b4iphone" class="header-anchor"&gt;&lt;/a&gt;2007 年：iPhone
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/054-ec78bc80.png"&gt;&lt;/p&gt;
&lt;p&gt;史蒂夫·乔布斯 (Steve Jobs) 推出了苹果公司的第一款智能手机，并通过恶作剧电话从附近的星巴克订购了 4,000 杯拿铁咖啡。iPhone 也是美国第一款没有实体键盘的智能手机，并成为有史以来最畅销的小工具，迄今为止销量已超过 22 亿部，并推动了各种基于应用程序 APP 的互联网公司的发展。&lt;/p&gt;
&lt;h2 id="2008大型强子对撞机"&gt;&lt;a href="#2008%e5%a4%a7%e5%9e%8b%e5%bc%ba%e5%ad%90%e5%af%b9%e6%92%9e%e6%9c%ba" class="header-anchor"&gt;&lt;/a&gt;2008：大型强子对撞机
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/055-f124d9cd.png"&gt;&lt;/p&gt;
&lt;p&gt;欧洲能源研究组织 (CERN) 经过十年的建设，大型强子对撞机于 2008 年投入使用，成为世界上最大、最强大的粒子加速器，能够以接近光速推进能量束。2012 年，大型强子对撞机的测试将揭示希格斯玻色子的证据，希格斯玻色子是一种亚原子粒子，被认为有助于产生质量，因此也是宇宙的组成部分之一。该粒子的同名者彼得·希格斯（Peter Higgs）（他不同意其被称为“上帝粒子”）因在科学理解物质属性方面取得的进展而荣获 2013 年诺贝尔物理学奖。&lt;/p&gt;
&lt;h2 id="2009比特币"&gt;&lt;a href="#2009%e6%af%94%e7%89%b9%e5%b8%81" class="header-anchor"&gt;&lt;/a&gt;2009：比特币
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/056-73689a93.png"&gt;&lt;/p&gt;
&lt;p&gt;化名中本聪推出了第一种流行的加密货币，这是一种匿名的点对点加密现金形式。比特币使用区块链计算来分散和验证支付，并且几乎是防篡改（和解释）的。为了避免通货膨胀，比特币的总量被限制在2100万个。随着越来越多的货币被“开采”，流通中的货币数量也会增加，“开采”是一种消耗大量电力的计算过程。该货币的价值在 2017 年 12 月达到顶峰，一枚比特币价值超过 19,000 美元。&lt;/p&gt;
&lt;h2 id="2010siri"&gt;&lt;a href="#2010siri" class="header-anchor"&gt;&lt;/a&gt;2010：Siri
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/057-ffb01cef.png"&gt;&lt;/p&gt;
&lt;p&gt;Apple 的数字助理作为 iOS 应用程序发布；用户只需对着 iPhone 说话即可询问信息和方向，并提示其他手机功能。尽管 Siri 1.0 存在缺陷，并且难以理解某些声音和口音，但它于 2011 年 10 月正式集成到 iPhone 4S 中，并且此后进行了更新，包括更多语言、更好的语音识别软件和英国口音选项。Siri 预示着更多语音激活虚拟助手的迅速推出，例如亚马逊的 Alexa 和微软的 Cortana（均为 2014 年）。&lt;/p&gt;
&lt;h2 id="2011好奇号漫游车"&gt;&lt;a href="#2011%e5%a5%bd%e5%a5%87%e5%8f%b7%e6%bc%ab%e6%b8%b8%e8%bd%a6" class="header-anchor"&gt;&lt;/a&gt;2011：好奇号漫游车
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/058-965264a2.png"&gt;&lt;/p&gt;
&lt;p&gt;好奇号于 2011 年 11 月从卡纳维拉尔角发射升空，并于次年 8 月登陆火星——这一事件因飞行总监（后来成为《大众力学》撰稿人）博巴克·费多西 (Bobak Ferdowsi) 的经典发型而成为标志性事件。火星车的目标是调查火星上的环境条件，并确定它是否适合微生物（或许也适合人类）生命。它是有史以来登陆火星的最先进的火星车，可以收集详细的图像和环境样本进行分析并发回地球。&lt;/p&gt;
&lt;h2 id="2012-年谷歌的机器学习项目"&gt;&lt;a href="#2012-%e5%b9%b4%e8%b0%b7%e6%ad%8c%e7%9a%84%e6%9c%ba%e5%99%a8%e5%ad%a6%e4%b9%a0%e9%a1%b9%e7%9b%ae" class="header-anchor"&gt;&lt;/a&gt;2012 年：谷歌的机器学习项目
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/059-d7a1d4bd.png"&gt;&lt;/p&gt;
&lt;p&gt;《纽约时报》报道称，作为 Google 深度学习研究的一部分，由 16,000 台计算机组成的集群已经自学如何识别猫。这些进步可以说推动科技行业更加认真地追求人工智能和机器学习项目，包括自动驾驶汽车技术、面部识别软件（Face ID 和 Facebook 上的自动标记）以及帮助 Alexa 等语音助手获得信息的技术。随着时间的推移变得更聪明。&lt;/p&gt;
&lt;h2 id="2013阿特拉斯"&gt;&lt;a href="#2013%e9%98%bf%e7%89%b9%e6%8b%89%e6%96%af" class="header-anchor"&gt;&lt;/a&gt;2013：阿特拉斯
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/060-f61e8d6f.png"&gt;&lt;/p&gt;
&lt;p&gt;机器人革命还没有到来，但如果真的到来，很难想象 Atlas 不会处于领先地位。该机器人由波士顿动力公司于 2013 年制造，随着它学习越来越多的技巧，它仍然具有令人惊叹的能力&lt;/p&gt;
&lt;h2 id="2014血液净化器"&gt;&lt;a href="#2014%e8%a1%80%e6%b6%b2%e5%87%80%e5%8c%96%e5%99%a8" class="header-anchor"&gt;&lt;/a&gt;2014：血液净化器
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/061-8255a569.png"&gt;&lt;/p&gt;
&lt;p&gt;2014年，世界开始认识到西非埃博拉病毒疫情的严重性。这是一个关于许多与疾病作斗争的人的令人难以置信的勇敢的故事，但一个小装置恰逢其时地出现了，它可以帮助解决这一问题——血液净化器。《时代》杂志将该设备列为 2014 年最佳发明之一，该杂志称该设备的工作原理是使用“专门设计的连接到透析机的药筒”，本质上是从血液中吸取埃博拉病毒。该设备还可以对抗肝炎和癌症。&lt;/p&gt;
&lt;h2 id="2015可重复使用火箭"&gt;&lt;a href="#2015%e5%8f%af%e9%87%8d%e5%a4%8d%e4%bd%bf%e7%94%a8%e7%81%ab%e7%ae%ad" class="header-anchor"&gt;&lt;/a&gt;2015：可重复使用火箭
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/062-58069bd7.png"&gt;&lt;/p&gt;
&lt;p&gt;Blue Origin 的 New Shepherd 和 SpaceX 的 Falcon 9 火箭在发射后均成功垂直着陆。多用途火箭可以大幅降低太空旅行仍然高昂的成本，SpaceX 与 NASA 的合作已经降低了这一成本。SpaceX 创始人埃隆·马斯克 (Elon Musk) 宣称，猎鹰 9 号的发射是朝着他殖民火星的最终目标迈出的一步——我们可能需要比预期更早地实现这一目标。&lt;/p&gt;
&lt;h2 id="2016oculus-rift"&gt;&lt;a href="#2016oculus-rift" class="header-anchor"&gt;&lt;/a&gt;2016：Oculus Rift
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/063-fa3b6936.png"&gt;&lt;/p&gt;
&lt;p&gt;自 2014 年 Facebook 以 20 亿美元收购 Facebook 两年后，Palmer Luckey 的虚拟现实公司发布了第一款耳机。护目镜内部的高分辨率屏幕会投射立体图像来模仿正常视觉，并让用户的大脑相信他们看到的是真实的东西，即使那东西是一个巨大的杀手机器人。虽然这款耳机主要用作游戏插件，但随后也适用于医学教育和驾驶员培训等不同用途。然而，Facebook 在 2018 年底取消了第二代 Rift 的生产。&lt;/p&gt;
&lt;h2 id="2017-年特斯拉-model-3"&gt;&lt;a href="#2017-%e5%b9%b4%e7%89%b9%e6%96%af%e6%8b%89-model-3" class="header-anchor"&gt;&lt;/a&gt;2017 年：特斯拉 Model 3
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/064-211af55e.png"&gt;&lt;/p&gt;
&lt;p&gt;埃隆·马斯克 (Elon Musk) 的电动汽车公司开始生产 Model 3，迈出了向主流迈进的最大一步。Model 3 是一款续航里程为 310 英里、预计普通售价为 35,000 美元的全电动汽车。尽管生产延迟且随后开始接受预订，但截至 2018 年第三季度，按收入计算，Model 3 仍是美国最畅销的汽车。&lt;/p&gt;
&lt;h2 id="2018金属3d打印"&gt;&lt;a href="#2018%e9%87%91%e5%b1%9e3d%e6%89%93%e5%8d%b0" class="header-anchor"&gt;&lt;/a&gt;2018：金属3D打印
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/065-c9906fec.png"&gt;&lt;/p&gt;
&lt;p&gt;3D 打印金属零件有潜力通过加快生产速度并使定制（或维持多年保修）更具成本效益来彻底改变制造业务；零件可以更轻、更坚固，并且可以以传统制造无法适应的方式成型。9 月，惠普开放其工业级 Metal Jet 打印机的预订，预计将于 2020 年底上市；早期客户包括大众汽车和 Primo 医疗集团。&lt;/p&gt;
&lt;h2 id="2019世界上最大的电动车"&gt;&lt;a href="#2019%e4%b8%96%e7%95%8c%e4%b8%8a%e6%9c%80%e5%a4%a7%e7%9a%84%e7%94%b5%e5%8a%a8%e8%bd%a6" class="header-anchor"&gt;&lt;/a&gt;2019：世界上最大的电动车
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/066-503183c8.png"&gt;&lt;/p&gt;
&lt;p&gt;我们已经看到了电动车的未来，而且它的规模非常庞大。虽然电动车正在全球范围内迅速普及，但大多数电动引擎仍然局限于较小的车辆。有人认为，真正的重工作仍然是由燃气大户的柴油引擎来做的。但2019年，世界上最大的电动车——Elekto Dumper的出现打破了电动车无法承受重工作的规则。&lt;/p&gt;
&lt;p&gt;e-Dumper 以小松 HB 605-7 为模型，长 30 英尺、宽 14 英尺、高 14 英尺，轮胎高 6 英尺，翻斗床长达 28 英尺。&lt;/p&gt;
&lt;p&gt;Kuhn Schweitz 制造了 eDumper，用于从采石场来回搬运泥灰岩。该公司声称，一天内从采石场到水泥厂往返 20 次，可产生 200 千瓦时的剩余能源（或每年 77 兆瓦时）。相比之下，普通自卸卡车每年使用 11,000 至 22,000 加仑柴油。&lt;/p&gt;
&lt;h2 id="2020covid-19-疫苗"&gt;&lt;a href="#2020covid-19-%e7%96%ab%e8%8b%97" class="header-anchor"&gt;&lt;/a&gt;2020：Covid-19 疫苗
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/067-a6ba3247.png"&gt;&lt;/p&gt;
&lt;p&gt;首例新型冠状病毒 Covid-19 于 2019 年 12 月被发现，世界卫生组织随后于 2020 年 3 月 11 日宣布其为大流行病。为了减缓这种新型易传染病毒的破坏性影响，制药公司和研究人员优先开发 Covid-19 疫苗。&lt;/p&gt;
&lt;p&gt;辉瑞-BioNTech 利用免疫学家 Drew Weissman 和生物化学家 Katalin Karikó 于 2005 年开发的 mRNA 技术，成为第一家开发 FDA 批准的紧急使用疫苗的公司，该疫苗于 2020 年 12 月 11 日向公众提供。Moderna 疫苗很快跟进一周后，大约两个月后，一剂强生疫苗也随之上市。辉瑞-BioNTech 和 Moderna 疫苗对原始病毒株的有效率为 95%，但随着时间的推移，有效率会降低；但所有疫苗都能显着降低住院或死亡的风险。&lt;/p&gt;
&lt;h2 id="2021疟疾疫苗"&gt;&lt;a href="#2021%e7%96%9f%e7%96%be%e7%96%ab%e8%8b%97" class="header-anchor"&gt;&lt;/a&gt;2021：疟疾疫苗
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/068-f262467a.png"&gt;&lt;/p&gt;
&lt;p&gt;第一个获得完全批准的疟疾疫苗 RTS,S（也称为 Mosquirix）已经等待了很长时间。该疫苗的开发始于 20 世纪 80 年代末，但该疫苗的试点计划直到 2019 年才在非洲推出，大约 96% 的疟疾相关死亡都发生在非洲。世界卫生组织 (WHO) 于 2021 年 10 月正式认可该疫苗。该疫苗的开发被认为是历史性的——根据世界卫生组织的数据，2020 年全球有 2.41 亿疟疾病例，估计有 627,000 人死亡。&lt;/p&gt;
&lt;h2 id="2022-年詹姆斯韦伯太空望远镜"&gt;&lt;a href="#2022-%e5%b9%b4%e8%a9%b9%e5%a7%86%e6%96%af%e9%9f%a6%e4%bc%af%e5%a4%aa%e7%a9%ba%e6%9c%9b%e8%bf%9c%e9%95%9c" class="header-anchor"&gt;&lt;/a&gt;2022 年：詹姆斯·韦伯太空望远镜
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-01-26-guo-qu-66-nian-de-66-xiang-zui-jia-nian-du-fa-ming/069-76ddcaef.png"&gt;&lt;/p&gt;
&lt;p&gt;詹姆斯·韦伯太空望远镜。作为红外望远镜，它比哈勃望远镜更灵敏，而且它现在是太空中最大的光学望远镜。研发于90年代中期开始，该望远镜于2021年底发射；它于 2022 年初全面投入运行。第一批图像于 7 月 12 日公开发布，它们并没有让人失望，甚至超出了所有人的预期。除了捕捉令人惊叹的图像之外，詹姆斯·韦伯太空望远镜还将帮助天文学家对太空最深处进行研究&lt;/p&gt;</description></item><item><title>Java 访问修饰符详解</title><link>https://xiaobox.github.io/p/2023-08-23-java-fang-wen-xiu-shi-fu-xiang-jie/</link><pubDate>Wed, 23 Aug 2023 15:27:10 +0000</pubDate><guid>https://xiaobox.github.io/p/2023-08-23-java-fang-wen-xiu-shi-fu-xiang-jie/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-08-23-java-fang-wen-xiu-shi-fu-xiang-jie/cover.jpg" alt="Featured image of post Java 访问修饰符详解" /&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-08-23-java-fang-wen-xiu-shi-fu-xiang-jie/001-6b11d6fa.png"&gt;&lt;/p&gt;
&lt;h2 id="类访问修饰"&gt;&lt;a href="#%e7%b1%bb%e8%ae%bf%e9%97%ae%e4%bf%ae%e9%a5%b0" class="header-anchor"&gt;&lt;/a&gt;类访问修饰
&lt;/h2&gt;&lt;p&gt;在 类（class） 上可以使用的访问修饰符有 &lt;code&gt;public&lt;/code&gt;、&lt;code&gt;protected&lt;/code&gt;、&lt;code&gt;默认（什么都不写）&lt;/code&gt;、&lt;code&gt;private&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;其中 &lt;code&gt;private&lt;/code&gt;、&lt;code&gt;protected&lt;/code&gt; 不能在普通类中写，只能在内部类中写（内部类中 4 种都可以写）&lt;/li&gt;
&lt;li&gt;普通的类访问修饰符只有 &lt;code&gt;public&lt;/code&gt;、&lt;code&gt;默认（什么都不写）&lt;/code&gt; 两种&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果一个类的访问修饰符是 &lt;code&gt;public&lt;/code&gt; ，那么 该类可以被任何其他类访问和继承。不受访问限制。其他类可以直接使用这个类创建对象，也可以继承这个类，并可以访问其中的公有方法和属性。&lt;/li&gt;
&lt;li&gt;如果一个类的访问修饰符是 &lt;code&gt;默认&lt;/code&gt;（啥都不写） ，该类的访问范围限定在定义该类的同一个包内。只有位于同一包下的其他类，才可以直接访问和使用这个类，包括访问其中公有成员和继承这个类。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="为什么普通类的类访问修饰符不能是-private-"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%99%ae%e9%80%9a%e7%b1%bb%e7%9a%84%e7%b1%bb%e8%ae%bf%e9%97%ae%e4%bf%ae%e9%a5%b0%e7%ac%a6%e4%b8%8d%e8%83%bd%e6%98%af-private-" class="header-anchor"&gt;&lt;/a&gt;为什么普通类的类访问修饰符不能是 private ？
&lt;/h3&gt;&lt;p&gt;答：如果一个类为 `private``, 则在其他文件或类中就无法访问和使用这个类，包括类中的成员变量和成员方法，也无法继承它，这明显不合理，都不能用它写个什么劲呐，哈哈。&lt;/p&gt;
&lt;h3 id="为什么普通类的类访问修饰符不能是-protected-"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%99%ae%e9%80%9a%e7%b1%bb%e7%9a%84%e7%b1%bb%e8%ae%bf%e9%97%ae%e4%bf%ae%e9%a5%b0%e7%ac%a6%e4%b8%8d%e8%83%bd%e6%98%af-protected-" class="header-anchor"&gt;&lt;/a&gt;为什么普通类的类访问修饰符不能是 protected ?
&lt;/h3&gt;&lt;p&gt;参考：https://stackoverflow.com/questions/3869556/why-can-a-class-not-be-defined-as-protected&lt;/p&gt;
&lt;p&gt;总结来说是因为没用，因为我们想像如果类修饰符可以为 &lt;code&gt;protected&lt;/code&gt;，那么无非是说除了本包的类可以访问这个类以外，在其他包的这个类的子类也可以访问它。我们仔细看这句话：“其他包的这个类的子类可以访问它”， 我得是你的子类才能访问你，但是我想成为你的子类得先能访问你呀，这不死锁了嘛，所以不合理。既然不合理就不用了嘛，所以对于普通类功能上就只有包内访问和包外访问两种，那么 &lt;code&gt;public&lt;/code&gt; 和 &lt;code&gt;default&lt;/code&gt; 就可以搞定了，所以就只剩下这两种了。当然这也是因为 java 没有“子包”或“包继承”这样的概念，否则&lt;code&gt;protected&lt;/code&gt;可能就有用了。&lt;/p&gt;
&lt;h3 id="为什么对于内部类可以用全部-4-种类访问修饰符-privatedefaultprotectedpublic"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e5%af%b9%e4%ba%8e%e5%86%85%e9%83%a8%e7%b1%bb%e5%8f%af%e4%bb%a5%e7%94%a8%e5%85%a8%e9%83%a8-4-%e7%a7%8d%e7%b1%bb%e8%ae%bf%e9%97%ae%e4%bf%ae%e9%a5%b0%e7%ac%a6-privatedefaultprotectedpublic" class="header-anchor"&gt;&lt;/a&gt;为什么对于内部类可以用全部 4 种类访问修饰符 (private、default、protected、public)？
&lt;/h3&gt;&lt;p&gt;说白了，还是看有用没用，没用就不需要那么多了，比如前面提到的普通类的类访问修饰符只有 2 个。我们来看看有什么用。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对于 &lt;code&gt;private&lt;/code&gt;，如果用它修饰内部类，那么表示仅在外部类内部使用，对外部类以外的类隐藏实现细节，还是比较有用的。总结来说，使用 &lt;code&gt;private&lt;/code&gt; 修饰内部类通常用于以下目的：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;封装实现细节：将内部类的实现细节隐藏在外部类内部，防止其他类直接访问和依赖内部类的实现细节&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实现辅助类：将内部类作为外部类的辅助类，只在外部类内部使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于&lt;code&gt;public&lt;/code&gt;，如果用它修饰内部类，意味着该内部类对外部类以外的其他类是可见的，并且可以被其他类直接访问。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使内部类可以被其他类直接使用：当内部类具有独立的功能或需要与外部类以外的代码进行交互时，可以使用 public 修饰内部类，以便其他类可以直接访问和使用该内部类。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;其他类可以直接访问该内部类：其他类可以通过外部类和内部类的名称直接访问该内部类，包括创建内部类的实例、调用内部类的方法和访问内部类的成员变量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内部类的可见性扩展到外部类以外：内部类的可见性不再限于外部类内部，而是对外部类以外的其他类开放。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;具体来说，使用 &lt;code&gt;public&lt;/code&gt; 修饰内部类会产生以下影响：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 &lt;code&gt;public&lt;/code&gt; 修饰内部类通常用于以下目的：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于 &lt;code&gt;default&lt;/code&gt; ，如果用它修饰内部类（即没有显式地使用任何访问修饰符），那么该内部类将具有默认访问级别。这意味着内部类对于外部类的其他成员和同一包中的其他类是可见的，但对于外部类所在包之外的类是不可见的。使用默认访问修饰符的内部类通常用于以下目的：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;封装实现细节：将内部类的实现细节隐藏在外部类内部和同一包中的其他类之间，防止外部包中的类直接访问和依赖内部类的实现细节。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制访问范围：将内部类限制在外部类和同一包中，以控制内部类的可见性和使用范围。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于 &lt;code&gt;protected&lt;/code&gt;，如果用它修饰内部类， 那么被 &lt;code&gt;protected&lt;/code&gt; 修饰的内部类对于外部类和外部类的子类是可见的，子类可以直接访问该内部类，并创建其实例、调用其方法以及访问其成员变量。另外同一包中的其他类也可以访问该内部类。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你看 内部类可以用 &lt;code&gt;protected&lt;/code&gt; ，是因为人家有外部类，可以明确父子类继承关系，但普通类就不行（原因上文说过）。另外的 3 种访问修饰符也是各有各的用途，所以内部类可以使用 全部 4 种访问修饰符。&lt;/p&gt;
&lt;h2 id="成员变量和成员方法访问修饰"&gt;&lt;a href="#%e6%88%90%e5%91%98%e5%8f%98%e9%87%8f%e5%92%8c%e6%88%90%e5%91%98%e6%96%b9%e6%b3%95%e8%ae%bf%e9%97%ae%e4%bf%ae%e9%a5%b0" class="header-anchor"&gt;&lt;/a&gt;成员变量和成员方法访问修饰
&lt;/h2&gt;&lt;p&gt;成员变量和成员方法的访问修饰符和内部类一样都是可以使用全部的 4 个&lt;/p&gt;
&lt;p&gt;它的可访问性也如本文开头的那个图描述的，从低到高依次是 &lt;code&gt;private&lt;/code&gt;、&lt;code&gt;default&lt;/code&gt;、&lt;code&gt;protected&lt;/code&gt;、&lt;code&gt;public&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;其实没啥好说的，跟类的大致意思一样，但有 2 个点需要注意一下：&lt;/p&gt;
&lt;p&gt;第一个是 &lt;code&gt;private&lt;/code&gt;，如果类的构造方法用 &lt;code&gt;private&lt;/code&gt; 修饰，那么这个类无法继承，也无法直接创建类对象，需要使用间接的方法，如单例模式&lt;/p&gt;
&lt;p&gt;另一个是 &lt;code&gt;protected&lt;/code&gt; ，在方法调用上 &lt;code&gt;protected&lt;/code&gt; 就更能体现出它的 “保护” 意味了。比如&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不同包下，在子类中通过父类引用不可以访问其 protected 方法&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;protected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;protect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;protect field&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;protected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;i am parent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Son1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parent1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// parent1.getMessage(); 错误&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parent2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Son1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// parent2.getMessage(); 错误&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;不同包下，在子类中通过该子类引用可以访问其 protected 方法，也可以在子类方法中直接调用， 还可以通过 super 关键字调用父类中的该方法&lt;/li&gt;
&lt;li&gt;不同包下，在子类中不能通过另一个子类引用访问共同基类的 protected 方法&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“保护” 的作用在方法调用时体现的比较明显，另外还可以在一定程度上保证继承体系的稳定，不被随意破坏。合理地利用 &lt;code&gt;protected&lt;/code&gt; 可以让代码具有良好的封装和可扩展性。下次你在某框架中再看到 &lt;code&gt;protected&lt;/code&gt; 时应该知道它为什么用这个来修饰了。比如 Spring 框架中的&lt;code&gt;AbstractApplicationContext&lt;/code&gt; 类，有个 &lt;code&gt;prepareRefresh()&lt;/code&gt; 方法：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-08-23-java-fang-wen-xiu-shi-fu-xiang-jie/002-70906fc6.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prepareRefresh()&lt;/code&gt;方法使用&lt;code&gt;protected&lt;/code&gt;修饰符来限制其访问范围。这是因为&lt;code&gt;prepareRefresh()&lt;/code&gt;方法是一个在应用程序上下文刷新之前执行的关键步骤，它包含了一些框架内部的初始化逻辑和准备工作。&lt;/li&gt;
&lt;li&gt;使用&lt;code&gt;protected&lt;/code&gt;修饰符可以将&lt;code&gt;prepareRefresh()&lt;/code&gt;方法限制在框架内部和继承体系中可见，防止外部代码直接调用该方法。这样的设计可以确保框架在进行刷新之前能够按照预期的顺序执行必要的初始化操作，同时避免外部代码干扰或绕过这些操作。&lt;/li&gt;
&lt;li&gt;此外，将&lt;code&gt;prepareRefresh()&lt;/code&gt;方法标记为&lt;code&gt;protected&lt;/code&gt;还为子类提供了一种扩展和定制的机制。子类可以通过继承&lt;code&gt;AbstractApplicationContext&lt;/code&gt;并重写&lt;code&gt;prepareRefresh()&lt;/code&gt;方法，以添加或修改特定的初始化逻辑，以满足其特定需求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://juejin.cn/post/6844903517988061191" target="_blank" rel="noopener"
 &gt;https://juejin.cn/post/6844903517988061191&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>