<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>一个旅人</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://blog.codenav.top/</id>
  <link href="https://blog.codenav.top/" rel="alternate"/>
  <link href="https://blog.codenav.top/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, 一个旅人</rights>
  <subtitle>程序设计 · 技术分享 · 思考记录</subtitle>
  <title>旅人小站</title>
  <updated>2026-05-22T03:50:09.098Z</updated>
  <entry>
    <author>
      <name>一个旅人</name>
    </author>
    <category term="技术总结" scheme="https://blog.codenav.top/categories/%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/"/>
    <category term="数据结构" scheme="https://blog.codenav.top/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
    <category term="算法" scheme="https://blog.codenav.top/tags/%E7%AE%97%E6%B3%95/"/>
    <content>
      <![CDATA[<h1 id="数据结构核心总结：线性表、链表、栈与队列-🚀"><a href="#数据结构核心总结：线性表、链表、栈与队列-🚀" class="headerlink" title="数据结构核心总结：线性表、链表、栈与队列 🚀"></a>数据结构核心总结：线性表、链表、栈与队列 🚀</h1><blockquote><p>数据结构是计算机存储、组织数据的方式。好的数据结构能够显著提升程序的运行效率。本文将系统总结<strong>线性表</strong>、<strong>链表</strong>、<strong>栈</strong>和<strong>队列</strong>这四种最基础且应用最广泛的数据结构，帮助你建立完整的知识体系。</p></blockquote><hr><h2 id="📖-目录"><a href="#📖-目录" class="headerlink" title="📖 目录"></a>📖 目录</h2><ol><li><a href="#%E7%BA%BF%E6%80%A7%E8%A1%A8%E5%9F%BA%E7%A1%80">线性表基础</a></li><li><a href="#%E9%A1%BA%E5%BA%8F%E8%A1%A8%E4%B8%8E%E9%93%BE%E8%A1%A8">顺序表与链表</a></li><li><a href="#%E5%8D%95%E5%90%91%E9%93%BE%E8%A1%A8">单向链表</a></li><li><a href="#%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8%E4%B8%8E%E5%BE%AA%E7%8E%AF%E9%93%BE%E8%A1%A8">双向链表与循环链表</a></li><li><a href="#%E6%A0%88">栈</a></li><li><a href="#%E9%98%9F%E5%88%97">队列</a></li><li><a href="#%E6%80%BB%E7%BB%93%E5%AF%B9%E6%AF%94">总结对比</a></li></ol><hr><h2 id="线性表基础"><a href="#线性表基础" class="headerlink" title="线性表基础"></a>线性表基础</h2><h3 id="什么是线性表？"><a href="#什么是线性表？" class="headerlink" title="什么是线性表？"></a>什么是线性表？</h3><p><strong>线性表（Linear List）</strong> 是由 n 个具有相同特性的数据元素组成的<strong>有序序列</strong>。它是数据结构中最简单、最基本的一种结构。</p><p>线性表的基本特征：</p><ul><li>存在唯一的”第一个”元素</li><li>存在唯一的”最后一个”元素</li><li>除第一个元素外，每个元素都有且仅有一个前驱元素</li><li>除最后一个元素外，每个元素都有且仅有一个后继元素</li></ul><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>graph LR    A[元素1] --> B[元素2]    B --> C[元素3]    C --> D[元素4]    E[元素n-1] --> F[元素n]    style A fill:#90EE90    style F fill:#FFB6C1</pre></div><h3 id="线性表的抽象数据类型"><a href="#线性表的抽象数据类型" class="headerlink" title="线性表的抽象数据类型"></a>线性表的抽象数据类型</h3><p>线性表的操作主要包括：</p><table><thead><tr><th>操作</th><th>说明</th></tr></thead><tbody><tr><td><code>initList()</code></td><td>初始化线性表</td></tr><tr><td><code>length()</code></td><td>获取线性表长度</td></tr><tr><td><code>get(i)</code></td><td>获取第 i 个位置的元素</td></tr><tr><td><code>insert(i, e)</code></td><td>在第 i 个位置插入元素 e</td></tr><tr><td><code>delete(i)</code></td><td>删除第 i 个位置的元素</td></tr><tr><td><code>isEmpty()</code></td><td>判断线性表是否为空</td></tr><tr><td><code>clear()</code></td><td>清空线性表</td></tr></tbody></table><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[开始] --> B{线性表是否为空?}    B -->|是| C[执行特殊处理]    B -->|否| D[查找目标位置]    D --> E{位置有效?}    E -->|是| F[执行插入/删除操作]    E -->|否| G[返回错误]    F --> H[长度变化]    H --> I[结束]    C --> I    G --> I</pre></div><hr><h2 id="顺序表与链表"><a href="#顺序表与链表" class="headerlink" title="顺序表与链表"></a>顺序表与链表</h2><p>线性表有两种主要的存储方式：<strong>顺序存储</strong>和<strong>链式存储</strong>。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[线性表] --> B[顺序表]    A --> C[链表]    B --> D[使用连续内存空间存储]    C --> E[使用指针连接各元素]    D --> F[随机访问 O1]    E --> G[插入删除 On]    F --> H[空间固定]    G --> I[空间动态]</pre></div><h3 id="顺序表（Sequential-List）"><a href="#顺序表（Sequential-List）" class="headerlink" title="顺序表（Sequential List）"></a>顺序表（Sequential List）</h3><p>顺序表使用一段<strong>连续的存储单元</strong>依次存储线性表中的元素。</p><p><strong>优点：</strong></p><ul><li>🔥 随机访问能力强，查询速度快（时间复杂度 O(1)）</li><li>🔥 缓存命中率高，因为内存连续</li></ul><p><strong>缺点：</strong></p><ul><li>❌ 插入和删除操作需要移动大量元素（时间复杂度 O(n)）</li><li>❌ 存储空间固定，大小受限制</li><li>❌ 需要预先分配足够的连续内存空间</li></ul><h3 id="链表（Linked-List）"><a href="#链表（Linked-List）" class="headerlink" title="链表（Linked List）"></a>链表（Linked List）</h3><p>链表通过<strong>指针</strong>将一系列元素连接起来，每个元素包含数据域和指针域。</p><p><strong>优点：</strong></p><ul><li>✅ 插入和删除操作不需要移动元素（时间复杂度 O(1)）</li><li>✅ 不需要预先分配固定大小的空间</li><li>✅ 可以动态扩展</li></ul><p><strong>缺点：</strong></p><ul><li>❌ 不支持随机访问，查询需要遍历（时间复杂度 O(n)）</li><li>❌ 每个元素需要额外的指针空间</li><li>❌ 缓存命中率较低</li></ul><hr><h2 id="单向链表"><a href="#单向链表" class="headerlink" title="单向链表"></a>单向链表</h2><h3 id="单向链表结构"><a href="#单向链表结构" class="headerlink" title="单向链表结构"></a>单向链表结构</h3><p>单向链表（Singly Linked List）是链表中最简单的一种，每个节点包含<strong>数据域</strong>和<strong>指向下一个节点的指针</strong>。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>graph LR    subgraph 单向链表        A[HEAD] --> B[Node1|Data: 10|Next: →]        B --> C[Node2|Data: 20|Next: →]        C --> D[Node3|Data: 30|Next: →]        D --> E[NULL]    end    style A fill:#87CEEB    style E fill:#FFB6C1</pre></div><h3 id="Java-实现单向链表"><a href="#Java-实现单向链表" class="headerlink" title="Java 实现单向链表"></a>Java 实现单向链表</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 单向链表节点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span>&lt;E&gt; &#123;</span><br><span class="line">    E data;       <span class="comment">// 数据域</span></span><br><span class="line">    Node&lt;E&gt; next; <span class="comment">// 指针域，指向下一个节点</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Node</span><span class="params">(E data)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.data = data;</span><br><span class="line">        <span class="built_in">this</span>.next = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 单向链表实现</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SinglyLinkedList</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> Node&lt;E&gt; head; <span class="comment">// 头节点</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> size;     <span class="comment">// 链表长度</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">SinglyLinkedList</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.head = <span class="keyword">new</span> <span class="title class_">Node</span>&lt;&gt;(<span class="literal">null</span>); <span class="comment">// 虚拟头节点</span></span><br><span class="line">        <span class="built_in">this</span>.size = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在链表头部添加元素</span></span><br><span class="line"><span class="comment">     * 时间复杂度：O(1)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addFirst</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        Node&lt;E&gt; newNode = <span class="keyword">new</span> <span class="title class_">Node</span>&lt;&gt;(element);</span><br><span class="line">        newNode.next = head.next;</span><br><span class="line">        head.next = newNode;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在链表尾部添加元素</span></span><br><span class="line"><span class="comment">     * 时间复杂度：O(n)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addLast</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        Node&lt;E&gt; newNode = <span class="keyword">new</span> <span class="title class_">Node</span>&lt;&gt;(element);</span><br><span class="line">        Node&lt;E&gt; current = head;</span><br><span class="line">        <span class="keyword">while</span> (current.next != <span class="literal">null</span>) &#123;</span><br><span class="line">            current = current.next;</span><br><span class="line">        &#125;</span><br><span class="line">        current.next = newNode;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在指定位置插入元素</span></span><br><span class="line"><span class="comment">     * 时间复杂度：O(n)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> index, E element)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="number">0</span> || index &gt; size) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IndexOutOfBoundsException</span>(<span class="string">&quot;Index: &quot;</span> + index + <span class="string">&quot;, Size: &quot;</span> + size);</span><br><span class="line">        &#125;</span><br><span class="line">        Node&lt;E&gt; newNode = <span class="keyword">new</span> <span class="title class_">Node</span>&lt;&gt;(element);</span><br><span class="line">        Node&lt;E&gt; current = head;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; index; i++) &#123;</span><br><span class="line">            current = current.next;</span><br><span class="line">        &#125;</span><br><span class="line">        newNode.next = current.next;</span><br><span class="line">        current.next = newNode;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除指定位置的元素</span></span><br><span class="line"><span class="comment">     * 时间复杂度：O(n)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">remove</span><span class="params">(<span class="type">int</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="number">0</span> || index &gt;= size) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IndexOutOfBoundsException</span>(<span class="string">&quot;Index: &quot;</span> + index + <span class="string">&quot;, Size: &quot;</span> + size);</span><br><span class="line">        &#125;</span><br><span class="line">        Node&lt;E&gt; current = head;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; index; i++) &#123;</span><br><span class="line">            current = current.next;</span><br><span class="line">        &#125;</span><br><span class="line">        Node&lt;E&gt; removedNode = current.next;</span><br><span class="line">        current.next = removedNode.next;</span><br><span class="line">        size--;</span><br><span class="line">        <span class="keyword">return</span> removedNode.data;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取指定位置的元素</span></span><br><span class="line"><span class="comment">     * 时间复杂度：O(n)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">get</span><span class="params">(<span class="type">int</span> index)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (index &lt; <span class="number">0</span> || index &gt;= size) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IndexOutOfBoundsException</span>(<span class="string">&quot;Index: &quot;</span> + index + <span class="string">&quot;, Size: &quot;</span> + size);</span><br><span class="line">        &#125;</span><br><span class="line">        Node&lt;E&gt; current = head.next;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; index; i++) &#123;</span><br><span class="line">            current = current.next;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> current.data;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 链表长度</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">size</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> size;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 判断链表是否为空</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isEmpty</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> size == <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="单向链表操作图解"><a href="#单向链表操作图解" class="headerlink" title="单向链表操作图解"></a>单向链表操作图解</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 插入操作        A1[原链表] --> A2["在 Node2 后插入 NodeX"]        A2 --> A3["Node2.next = NodeX"]        A3 --> A4["NodeX.next = Node3"]    end    subgraph 删除操作        B1[原链表] --> B2["删除 Node2"]        B2 --> B3["Node1.next = Node3"]        B3 --> B4["释放 Node2"]    end</pre></div><hr><h2 id="双向链表与循环链表"><a href="#双向链表与循环链表" class="headerlink" title="双向链表与循环链表"></a>双向链表与循环链表</h2><h3 id="双向链表"><a href="#双向链表" class="headerlink" title="双向链表"></a>双向链表</h3><p>双向链表（Doubly Linked List）的每个节点包含<strong>数据域</strong>、<strong>前驱指针</strong>和<strong>后继指针</strong>。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>graph LR    A[NULL] <--> B[Node1|Data: 10|Prev: ←|Next: →]    B <--> C[Node2|Data: 20|Prev: ←|Next: →]    C <--> D[Node3|Data: 30|Prev: ←|Next: →]    D <--> E[NULL]    style A fill:#FFB6C1    style E fill:#FFB6C1</pre></div><h3 id="双向链表-Java-实现"><a href="#双向链表-Java-实现" class="headerlink" title="双向链表 Java 实现"></a>双向链表 Java 实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 双向链表节点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">DNode</span>&lt;E&gt; &#123;</span><br><span class="line">    E data;</span><br><span class="line">    DNode&lt;E&gt; prev; <span class="comment">// 前驱指针</span></span><br><span class="line">    DNode&lt;E&gt; next; <span class="comment">// 后继指针</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">DNode</span><span class="params">(E data)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.data = data;</span><br><span class="line">        <span class="built_in">this</span>.prev = <span class="literal">null</span>;</span><br><span class="line">        <span class="built_in">this</span>.next = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 双向链表实现</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DoublyLinkedList</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> DNode&lt;E&gt; head; <span class="comment">// 头节点</span></span><br><span class="line">    <span class="keyword">private</span> DNode&lt;E&gt; tail; <span class="comment">// 尾节点</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> size;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">DoublyLinkedList</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.head = <span class="keyword">new</span> <span class="title class_">DNode</span>&lt;&gt;(<span class="literal">null</span>);</span><br><span class="line">        <span class="built_in">this</span>.tail = <span class="keyword">new</span> <span class="title class_">DNode</span>&lt;&gt;(<span class="literal">null</span>);</span><br><span class="line">        <span class="built_in">this</span>.head.next = tail;</span><br><span class="line">        <span class="built_in">this</span>.tail.prev = head;</span><br><span class="line">        <span class="built_in">this</span>.size = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在头部添加元素</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addFirst</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        DNode&lt;E&gt; newNode = <span class="keyword">new</span> <span class="title class_">DNode</span>&lt;&gt;(element);</span><br><span class="line">        newNode.next = head.next;</span><br><span class="line">        newNode.prev = head;</span><br><span class="line">        head.next.prev = newNode;</span><br><span class="line">        head.next = newNode;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 在尾部添加元素</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addLast</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        DNode&lt;E&gt; newNode = <span class="keyword">new</span> <span class="title class_">DNode</span>&lt;&gt;(element);</span><br><span class="line">        newNode.next = tail;</span><br><span class="line">        newNode.prev = tail.prev;</span><br><span class="line">        tail.prev.next = newNode;</span><br><span class="line">        tail.prev = newNode;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除指定节点</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(DNode&lt;E&gt; node)</span> &#123;</span><br><span class="line">        node.prev.next = node.next;</span><br><span class="line">        node.next.prev = node.prev;</span><br><span class="line">        size--;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="循环链表"><a href="#循环链表" class="headerlink" title="循环链表"></a>循环链表</h3><p>循环链表（Circular Linked List）是链表的一种变形，<strong>最后一个节点的指针指向头节点</strong>，形成环状结构。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>graph LR    A[HEAD] --> B[Node1]    B --> C[Node2]    C --> D[Node3]    D --> A    style A fill:#87CEEB</pre></div><p><strong>循环链表的特点：</strong></p><ul><li>🔄 没有 null 指针，所有节点形成闭环</li><li>🔄 从任意节点出发，都可以遍历整个链表</li><li>🔄 常用于需要循环遍历的场景（如约瑟夫问题）</li></ul><hr><h2 id="栈"><a href="#栈" class="headerlink" title="栈"></a>栈</h2><h3 id="什么是栈？"><a href="#什么是栈？" class="headerlink" title="什么是栈？"></a>什么是栈？</h3><p><strong>栈（Stack）</strong> 是一种特殊的线性表，它遵循 <strong>LIFO（Last In First Out）</strong> 原则——后进先出。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[入栈 Push] --> B["栈 Stack"]    B --> C[出栈 Pop]    A2["元素 D"] -->|压入| B    A3["元素 C"] -->|压入| B    A4["元素 B"] -->|压入| B    A5["元素 A"] -->|压入| B    B -->|弹出| R1["元素 D"]    style B fill:#FFD700</pre></div><h3 id="栈的基本操作"><a href="#栈的基本操作" class="headerlink" title="栈的基本操作"></a>栈的基本操作</h3><table><thead><tr><th>操作</th><th>说明</th><th>时间复杂度</th></tr></thead><tbody><tr><td><code>push(e)</code></td><td>将元素压入栈顶</td><td>O(1)</td></tr><tr><td><code>pop()</code></td><td>弹出栈顶元素</td><td>O(1)</td></tr><tr><td><code>peek()</code></td><td>查看栈顶元素</td><td>O(1)</td></tr><tr><td><code>isEmpty()</code></td><td>判断栈是否为空</td><td>O(1)</td></tr><tr><td><code>size()</code></td><td>获取栈的大小</td><td>O(1)</td></tr></tbody></table><h3 id="Java-栈实现"><a href="#Java-栈实现" class="headerlink" title="Java 栈实现"></a>Java 栈实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 栈接口</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Stack</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">push</span><span class="params">(E element)</span>;  <span class="comment">// 压栈</span></span><br><span class="line">    E <span class="title function_">pop</span><span class="params">()</span>;               <span class="comment">// 弹栈</span></span><br><span class="line">    E <span class="title function_">peek</span><span class="params">()</span>;              <span class="comment">// 查看栈顶</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">size</span><span class="params">()</span>;            <span class="comment">// 大小</span></span><br><span class="line">    <span class="type">boolean</span> <span class="title function_">isEmpty</span><span class="params">()</span>;     <span class="comment">// 是否为空</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 基于数组的栈实现</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArrayStack</span>&lt;E&gt; <span class="keyword">implements</span> <span class="title class_">Stack</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> Object[] elements;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> top;           <span class="comment">// 栈顶指针</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> capacity;      <span class="comment">// 栈容量</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ArrayStack</span><span class="params">(<span class="type">int</span> capacity)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.capacity = capacity;</span><br><span class="line">        <span class="built_in">this</span>.elements = <span class="keyword">new</span> <span class="title class_">Object</span>[capacity];</span><br><span class="line">        <span class="built_in">this</span>.top = -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">push</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (top &gt;= capacity - <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">StackOverflowError</span>(<span class="string">&quot;Stack is full!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        elements[++top] = element;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">pop</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;Stack is empty!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> (E) elements[top--];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">peek</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;Stack is empty!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> (E) elements[top];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">size</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> top + <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isEmpty</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> top == -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="栈的应用场景"><a href="#栈的应用场景" class="headerlink" title="栈的应用场景"></a>栈的应用场景</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>mindmap    root((栈的应用))        函数调用            调用栈            递归实现        表达式求值            中缀转后缀            后缀表达式计算        括号匹配            有效括号判断        浏览器前进后退            历史记录        撤销操作            编辑器撤销</pre></div><p><strong>典型应用：</strong></p><ol><li><strong>函数调用栈</strong> - 程序语言的函数调用管理</li><li><strong>括号匹配</strong> - 检验表达式中的括号是否合法</li><li><strong>表达式求值</strong> - 中缀表达式转后缀表达式</li><li><strong>深度优先搜索（DFS）</strong> - 图和树的遍历</li></ol><h3 id="括号匹配实例"><a href="#括号匹配实例" class="headerlink" title="括号匹配实例"></a>括号匹配实例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 有效的括号匹配</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isValid</span><span class="params">(String s)</span> &#123;</span><br><span class="line">    Stack&lt;Character&gt; stack = <span class="keyword">new</span> <span class="title class_">Stack</span>&lt;&gt;();</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> (<span class="type">char</span> c : s.toCharArray()) &#123;</span><br><span class="line">        <span class="keyword">if</span> (c == <span class="string">&#x27;(&#x27;</span> || c == <span class="string">&#x27;[&#x27;</span> || c == <span class="string">&#x27;&#123;&#x27;</span>) &#123;</span><br><span class="line">            stack.push(c);  <span class="comment">// 左括号入栈</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (stack.isEmpty()) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;  <span class="comment">// 没有左括号可以匹配</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="type">char</span> <span class="variable">top</span> <span class="operator">=</span> stack.pop();</span><br><span class="line">            <span class="keyword">if</span> ((c == <span class="string">&#x27;)&#x27;</span> &amp;&amp; top != <span class="string">&#x27;(&#x27;</span>) ||</span><br><span class="line">                (c == <span class="string">&#x27;]&#x27;</span> &amp;&amp; top != <span class="string">&#x27;[&#x27;</span>) ||</span><br><span class="line">                (c == <span class="string">&#x27;&#125;&#x27;</span> &amp;&amp; top != <span class="string">&#x27;&#123;&#x27;</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;  <span class="comment">// 括号不匹配</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> stack.isEmpty();  <span class="comment">// 栈空说明完全匹配</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h2><h3 id="什么是队列？"><a href="#什么是队列？" class="headerlink" title="什么是队列？"></a>什么是队列？</h3><p><strong>队列（Queue）</strong> 是一种特殊的线性表，它遵循 <strong>FIFO（First In First Out）</strong> 原则——先进先出。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[入队 Enqueue] --> B["队列 Queue"]    B --> C[出队 Dequeue]    A2["元素 A"] -->|加入队尾| B    A3["元素 B"] -->|加入队尾| B    A4["元素 C"] -->|加入队尾| B    B -->|移除队首| R1["元素 A"]    style B fill:#87CEEB</pre></div><h3 id="队列的基本操作"><a href="#队列的基本操作" class="headerlink" title="队列的基本操作"></a>队列的基本操作</h3><table><thead><tr><th>操作</th><th>说明</th><th>时间复杂度</th></tr></thead><tbody><tr><td><code>enqueue(e)</code></td><td>将元素加入队尾</td><td>O(1)</td></tr><tr><td><code>dequeue()</code></td><td>移除队首元素</td><td>O(1)</td></tr><tr><td><code>front()</code></td><td>查看队首元素</td><td>O(1)</td></tr><tr><td><code>rear()</code></td><td>查看队尾元素</td><td>O(1)</td></tr><tr><td><code>isEmpty()</code></td><td>判断队列是否为空</td><td>O(1)</td></tr></tbody></table><h3 id="Java-队列实现"><a href="#Java-队列实现" class="headerlink" title="Java 队列实现"></a>Java 队列实现</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 队列接口</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Queue</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">enqueue</span><span class="params">(E element)</span>;  <span class="comment">// 入队</span></span><br><span class="line">    E <span class="title function_">dequeue</span><span class="params">()</span>;              <span class="comment">// 出队</span></span><br><span class="line">    E <span class="title function_">front</span><span class="params">()</span>;                <span class="comment">// 查看队首</span></span><br><span class="line">    <span class="type">boolean</span> <span class="title function_">isEmpty</span><span class="params">()</span>;        <span class="comment">// 是否为空</span></span><br><span class="line">    <span class="type">int</span> <span class="title function_">size</span><span class="params">()</span>;               <span class="comment">// 大小</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 基于数组的循环队列实现</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CircularQueue</span>&lt;E&gt; <span class="keyword">implements</span> <span class="title class_">Queue</span>&lt;E&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> Object[] elements;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> front;        <span class="comment">// 队首指针</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> rear;         <span class="comment">// 队尾指针</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> capacity;     <span class="comment">// 队列容量</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> size;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">CircularQueue</span><span class="params">(<span class="type">int</span> capacity)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.capacity = capacity;</span><br><span class="line">        <span class="built_in">this</span>.elements = <span class="keyword">new</span> <span class="title class_">Object</span>[capacity];</span><br><span class="line">        <span class="built_in">this</span>.front = <span class="number">0</span>;</span><br><span class="line">        <span class="built_in">this</span>.rear = <span class="number">0</span>;</span><br><span class="line">        <span class="built_in">this</span>.size = <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">enqueue</span><span class="params">(E element)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (size == capacity) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;Queue is full!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        elements[rear] = element;</span><br><span class="line">        rear = (rear + <span class="number">1</span>) % capacity;</span><br><span class="line">        size++;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">dequeue</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;Queue is empty!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">E</span> <span class="variable">element</span> <span class="operator">=</span> (E) elements[front];</span><br><span class="line">        front = (front + <span class="number">1</span>) % capacity;</span><br><span class="line">        size--;</span><br><span class="line">        <span class="keyword">return</span> element;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> E <span class="title function_">front</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (isEmpty()) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalStateException</span>(<span class="string">&quot;Queue is empty!&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> (E) elements[front];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isEmpty</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> size == <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">size</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> size;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="循环队列原理图"><a href="#循环队列原理图" class="headerlink" title="循环队列原理图"></a>循环队列原理图</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 循环队列示意图        direction TB        A1["front=0"] --> A2["rear=4"]        A2 --> A3["capacity=8"]    end    subgraph 队列状态        direction LR        B1[0] --> B2[1]        B2 --> B3[2]        B3 --> B4[3]        B4 --> B5["A" fill:#90EE90]        B5 --> B6["B" fill:#90EE90]        B6 --> B7["C" fill:#90EE90]        B7 --> B8["D" fill:#90EE90]    end</pre></div><h3 id="队列的应用场景"><a href="#队列的应用场景" class="headerlink" title="队列的应用场景"></a>队列的应用场景</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>mindmap    root((队列的应用))        任务调度            线程池            打印机队列        广度优先搜索            BFS遍历            层级遍历        消息队列            异步通信            限流削峰        缓存策略            FIFO缓存            页面置换</pre></div><p><strong>典型应用：</strong></p><ol><li><strong>任务调度</strong> - 操作系统中的进程&#x2F;线程调度</li><li><strong>广度优先搜索（BFS）</strong> - 图和树的层级遍历</li><li><strong>消息队列</strong> - 异步通信、流量削峰</li><li><strong>缓存策略</strong> - LRU、LFU 等缓存算法</li></ol><h3 id="BFS-遍历实例"><a href="#BFS-遍历实例" class="headerlink" title="BFS 遍历实例"></a>BFS 遍历实例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用队列实现二叉树层序遍历</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> List&lt;List&lt;Integer&gt;&gt; <span class="title function_">levelOrder</span><span class="params">(TreeNode root)</span> &#123;</span><br><span class="line">    List&lt;List&lt;Integer&gt;&gt; result = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span> result;</span><br><span class="line">    </span><br><span class="line">    Queue&lt;TreeNode&gt; queue = <span class="keyword">new</span> <span class="title class_">LinkedList</span>&lt;&gt;();</span><br><span class="line">    queue.offer(root);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">while</span> (!queue.isEmpty()) &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">levelSize</span> <span class="operator">=</span> queue.size();</span><br><span class="line">        List&lt;Integer&gt; level = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; levelSize; i++) &#123;</span><br><span class="line">            <span class="type">TreeNode</span> <span class="variable">node</span> <span class="operator">=</span> queue.poll();</span><br><span class="line">            level.add(node.val);</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">if</span> (node.left != <span class="literal">null</span>) &#123;</span><br><span class="line">                queue.offer(node.left);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (node.right != <span class="literal">null</span>) &#123;</span><br><span class="line">                queue.offer(node.right);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        result.add(level);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="总结对比"><a href="#总结对比" class="headerlink" title="总结对比"></a>总结对比</h2><h3 id="四种数据结构对比"><a href="#四种数据结构对比" class="headerlink" title="四种数据结构对比"></a>四种数据结构对比</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[数据结构选择] --> B{主要操作是什么?}    B -->|只需要在一端操作| C{需要 FIFO 还是 LIFO?}    C -->|LIFO| D[栈 Stack]    C -->|FIFO| E[队列 Queue]    B -->|需要在中间插入删除| F{需要随机访问?}    F -->|是| G[顺序表 ArrayList]    F -->|否| H[链表 LinkedList]    D --> I["时间复杂度 O(1)"]    E --> I    G --> J["查询 O(1) / 插入删除 O(n)"]    H --> K["查询 O(n) / 插入删除 O(1)"]</pre></div><h3 id="复杂度对比表"><a href="#复杂度对比表" class="headerlink" title="复杂度对比表"></a>复杂度对比表</h3><table><thead><tr><th>数据结构</th><th>访问</th><th>插入</th><th>删除</th><th>空间</th></tr></thead><tbody><tr><td>顺序表</td><td>O(1)</td><td>O(n)</td><td>O(n)</td><td>O(n)</td></tr><tr><td>单向链表</td><td>O(n)</td><td>O(1)*</td><td>O(1)*</td><td>O(n)</td></tr><tr><td>双向链表</td><td>O(n)</td><td>O(1)*</td><td>O(1)*</td><td>O(n)</td></tr><tr><td>栈</td><td>-</td><td>O(1)</td><td>O(1)</td><td>O(n)</td></tr><tr><td>队列</td><td>-</td><td>O(1)</td><td>O(1)</td><td>O(n)</td></tr></tbody></table><blockquote><p>*注：O(1) 的前提是已经找到目标位置，否则需要 O(n) 的查找时间。</p></blockquote><h3 id="选择建议"><a href="#选择建议" class="headerlink" title="选择建议"></a>选择建议</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>graph LR    A["频繁查询"] --> D["顺序表 / ArrayList"]    B["频繁插入删除"] --> E["链表 / LinkedList"]    C["先进先出"] --> F["队列 Queue"]    D --> G["需要平衡"]    E --> G    F --> G    G --> H["LinkedList 实现 Queue"]</pre></div><p><strong>选择要点：</strong></p><ul><li>🔥 <strong>查询多、修改少</strong> → 选择 <code>ArrayList</code>（顺序表）</li><li>🔥 <strong>插入删除多、查询少</strong> → 选择 <code>LinkedList</code>（链表）</li><li>🔥 <strong>需要 LIFO</strong> → 选择 <code>Stack</code></li><li>🔥 <strong>需要 FIFO</strong> → 选择 <code>Queue</code></li></ul><hr><h2 id="📚-最后"><a href="#📚-最后" class="headerlink" title="📚 最后"></a>📚 最后</h2><p>线性表、链表、栈、队列是数据结构中最基础的概念，看似简单，却支撑着整个计算机世界的运行。理解它们的原理和适用场景，是成为优秀程序员的必经之路。</p><p>希望本文对你有所帮助！如果有任何问题，欢迎留言讨论 💬</p><hr><p><em>原创不易，转载请注明出处！</em></p>]]>
    </content>
    <id>https://blog.codenav.top/data-structures-linear/</id>
    <link href="https://blog.codenav.top/data-structures-linear/"/>
    <published>2026-05-22T03:45:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="数据结构核心总结：线性表、链表、栈与队列-🚀"><a href="#数据结构核心总结：线性表、链表、栈与队列-🚀" class="headerlink" title="数据结构核心总结：线性表、链表、栈与队列 🚀"></a>数据结构核心总结：线性表、链表、栈]]>
    </summary>
    <title>数据结构核心总结：线性表、链表、栈与队列</title>
    <updated>2026-05-22T03:50:09.098Z</updated>
  </entry>
  <entry>
    <author>
      <name>一个旅人</name>
    </author>
    <category term="Java" scheme="https://blog.codenav.top/categories/Java/"/>
    <category term="Java" scheme="https://blog.codenav.top/tags/Java/"/>
    <category term="进阶" scheme="https://blog.codenav.top/tags/%E8%BF%9B%E9%98%B6/"/>
    <content>
      <![CDATA[<h1 id="Java-进阶核心知识点总结-🚀"><a href="#Java-进阶核心知识点总结-🚀" class="headerlink" title="Java 进阶核心知识点总结 🚀"></a>Java 进阶核心知识点总结 🚀</h1><blockquote><p>本文将深入探讨 Java 进阶知识，包括 JVM 内存模型、垃圾回收机制、并发编程、集合源码、设计模式等核心内容。如果你已经掌握了 Java 基础，那么进阶之路从这里开始。</p></blockquote><hr><h2 id="📖-目录"><a href="#📖-目录" class="headerlink" title="📖 目录"></a>📖 目录</h2><ol><li><a href="#jvm-%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B">JVM 内存模型</a></li><li><a href="#%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6">垃圾回收机制</a></li><li><a href="#%E7%B1%BB%E5%8A%A0%E8%BD%BD%E6%9C%BA%E5%88%B6">类加载机制</a></li><li><a href="#%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B">并发编程</a></li><li><a href="#%E9%9B%86%E5%90%88%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90">集合源码解析</a></li><li><a href="#%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F">设计模式</a></li><li><a href="#%E5%B8%B8%E7%94%A8%E5%B7%A5%E5%85%B7%E7%B1%BB">常用工具类</a></li></ol><hr><h2 id="JVM-内存模型"><a href="#JVM-内存模型" class="headerlink" title="JVM 内存模型"></a>JVM 内存模型</h2><h3 id="为什么需要了解-JVM？"><a href="#为什么需要了解-JVM？" class="headerlink" title="为什么需要了解 JVM？"></a>为什么需要了解 JVM？</h3><p>很多初学者可能会问：我写 Java 代码又不需要直接操作内存，JVM 自动管理不就好了吗？</p><p>这个想法没错，但如果你想写出<strong>高性能</strong>、<strong>资源利用率高</strong>的代码，就必须了解 JVM。比如：</p><ul><li>什么时候对象会被回收？</li><li>为什么代码没问题但内存一直涨？</li><li>如何调优 JVM 参数？</li><li>如何排查 OOM（OutOfMemoryError）问题？</li></ul><p>这些问题都需要对 JVM 有深入了解。</p><h3 id="JVM-内存划分"><a href="#JVM-内存划分" class="headerlink" title="JVM 内存划分"></a>JVM 内存划分</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    subgraph JVM 运行时数据区        A[JVM 内存模型] --> B[线程共享区]        A --> C[线程私有区]        B --> D[堆 Heap]        B --> E[方法区 Method Area]        C --> F[虚拟机栈 VM Stack]        C --> G[本地方法栈 Native Stack]        C --> H[程序计数器 PC]    end    style A fill:#fff3e0    style B fill:#e3f2fd    style C fill:#e8f5e9</pre></div><h3 id="各区域详解"><a href="#各区域详解" class="headerlink" title="各区域详解"></a>各区域详解</h3><h4 id="1-程序计数器（PC-Register）"><a href="#1-程序计数器（PC-Register）" class="headerlink" title="1. 程序计数器（PC Register）"></a>1. 程序计数器（PC Register）</h4><p><strong>作用</strong>：当前线程所执行的字节码的行号指示器。</p><p><strong>特点</strong>：</p><ul><li>线程私有，每个线程都有自己的程序计数器</li><li>唯一一个不会发生 OutOfMemoryError 的区域</li><li>执行 Java 方法时记录字节码指令地址，执行 Native 方法时为空</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 举例：程序计数器的工作方式</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PCRDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">1</span>;        <span class="comment">// 字节码指令 0: iconst_1</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">b</span> <span class="operator">=</span> <span class="number">2</span>;        <span class="comment">// 字节码指令 2: iconst_2</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">c</span> <span class="operator">=</span> a + b;    <span class="comment">// 字节码指令 3: iadd</span></span><br><span class="line">        <span class="comment">// 程序计数器记录当前执行到哪条指令</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="2-虚拟机栈（VM-Stack）"><a href="#2-虚拟机栈（VM-Stack）" class="headerlink" title="2. 虚拟机栈（VM Stack）"></a>2. 虚拟机栈（VM Stack）</h4><p><strong>作用</strong>：存储方法调用时的局部变量、操作数栈、动态链接等信息。</p><p><strong>特点</strong>：</p><ul><li>线程私有，生命周期与线程相同</li><li>每个方法调用都会创建一个<strong>栈帧（Stack Frame）</strong></li><li>方法执行完毕，栈帧出栈</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StackDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        methodA();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">methodA</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line">        methodB(a);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">methodB</span><span class="params">(<span class="type">int</span> num)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> num * <span class="number">2</span>;</span><br><span class="line">        System.out.println(result);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    subgraph 虚拟机栈        A[main 栈帧] --> B[methodA 栈帧]        B --> C[methodB 栈帧]        style A fill:#e3f2fd        style B fill:#e8f5e9        style C fill:#fce4ec    end</pre></div><p><strong>常见错误</strong>：</p><ul><li><code>StackOverflowError</code>：栈溢出，通常是递归调用没有正确终止</li><li><code>OutOfMemoryError</code>：内存溢出，栈内存不足</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 栈溢出示例：递归没有终止条件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StackOverflowDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">recursive</span><span class="params">()</span> &#123;</span><br><span class="line">        recursive();  <span class="comment">// 无限递归，最终 StackOverflowError</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        recursive();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="3-本地方法栈（Native-Stack）"><a href="#3-本地方法栈（Native-Stack）" class="headerlink" title="3. 本地方法栈（Native Stack）"></a>3. 本地方法栈（Native Stack）</h4><p><strong>作用</strong>：为 JVM 调用本地方法（Native Method）服务。</p><p><strong>与虚拟机栈的区别</strong>：</p><ul><li>虚拟机栈为 Java 方法服务</li><li>本地方法栈为 Native 方法服务</li><li>HotSpot 虚拟机将两者合二为一</li></ul><h4 id="4-堆（Heap）"><a href="#4-堆（Heap）" class="headerlink" title="4. 堆（Heap）"></a>4. 堆（Heap）</h4><p><strong>作用</strong>：几乎所有对象实例和数组都在堆上分配内存。</p><p><strong>特点</strong>：</p><ul><li>线程共享，是 JVM 管理内存中最大的一块</li><li>垃圾收集器（GC）主要管理的就是堆内存</li><li>分为年轻代、老年代、永久代（Java 8+ 变为元空间）</li></ul><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    subgraph 堆内存        A[堆 Heap] --> B[年轻代 Young Generation]        A --> C[老年代 Old Generation]        B --> D[Eden 区]        B --> E[S0 区 Survivor From]        B --> F[S1 区 Survivor To]        C --> G[Tenured 区]    end    style A fill:#fff3e0    style B fill:#e3f2fd    style C fill:#e8f5e9</pre></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 堆内存演示：创建大量对象</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HeapDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 不断创建对象，观察内存变化</span></span><br><span class="line">        List&lt;<span class="type">byte</span>[]&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="comment">// 每个 byte 数组约 1MB</span></span><br><span class="line">            list.add(<span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span> * <span class="number">1024</span>]);</span><br><span class="line">            System.out.println(<span class="string">&quot;已分配：&quot;</span> + list.size() + <span class="string">&quot; MB&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="5-方法区（Method-Area）"><a href="#5-方法区（Method-Area）" class="headerlink" title="5. 方法区（Method Area）"></a>5. 方法区（Method Area）</h4><p><strong>作用</strong>：存储类信息（类的字节码、版本号）、常量、静态变量、即时编译器编译后的代码等。</p><p><strong>特点</strong>：</p><ul><li>线程共享</li><li>在 HotSpot JVM 中，Java 8 之前用永久代实现，Java 8 之后用元空间（Metaspace）实现</li><li>元空间使用本地内存，不受 JVM 堆大小限制</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MethodAreaDemo</span> &#123;</span><br><span class="line">    <span class="comment">// 静态变量存储在方法区</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> <span class="variable">staticVar</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量存储在方法区的常量池</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">CONSTANT</span> <span class="operator">=</span> <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="comment">// 静态代码块也在方法区</span></span><br><span class="line">        System.out.println(<span class="string">&quot;类加载时执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 普通方法不在方法区，具体在虚拟机栈的栈帧中</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="内存溢出示例"><a href="#内存溢出示例" class="headerlink" title="内存溢出示例"></a>内存溢出示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// OOM 示例：常量池溢出（Java 7 之前会发生）</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OOMDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 使用 String.intern() 将字符串放入常量池</span></span><br><span class="line">        <span class="comment">// 如果不断添加字符串到常量池，最终会 OOM</span></span><br><span class="line">        List&lt;String&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            list.add(String.valueOf(i++).intern());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="垃圾回收机制"><a href="#垃圾回收机制" class="headerlink" title="垃圾回收机制"></a>垃圾回收机制</h2><h3 id="什么是垃圾回收？"><a href="#什么是垃圾回收？" class="headerlink" title="什么是垃圾回收？"></a>什么是垃圾回收？</h3><p>垃圾回收（Garbage Collection，简称 GC）是 JVM 自动管理内存的机制，<strong>自动回收不再使用的对象</strong>，防止内存泄漏。</p><p><strong>为什么需要 GC？</strong></p><p>在 C&#x2F;C++ 中，内存需要程序员手动分配和释放，容易出现：</p><ul><li><strong>内存泄漏</strong>：分配后忘记释放，内存越来越少</li><li><strong>野指针</strong>：释放后继续使用，导致程序崩溃</li><li><strong>双重释放</strong>：同一块内存释放两次</li></ul><p>Java 通过 GC 解决了这些问题，程序员只需要关心对象的创建，不用关心释放。</p><h3 id="判断对象是否可回收"><a href="#判断对象是否可回收" class="headerlink" title="判断对象是否可回收"></a>判断对象是否可回收</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[判断对象是否可回收] --> B[引用计数法]    A --> C[可达性分析]    B --> B1[每个对象一个引用计数器]    B1 --> B2[有引用+1，删除-1]    B2 --> B3[计数器为0可回收]    B3 --> B4[无法处理循环引用]    C --> C1[GC Roots]    C1 --> C2[从 GC Roots 向下搜索]    C2 --> C3[走过的路径叫引用链]    C3 --> C4[不在引用链上=可回收]    style A fill:#fff3e0</pre></div><h4 id="1-引用计数法"><a href="#1-引用计数法" class="headerlink" title="1. 引用计数法"></a>1. 引用计数法</h4><p>给对象添加一个引用计数器，每当有一个地方引用它时，计数器加 1；引用失效时，计数器减 1。任何时刻计数器为 0 的对象就是不可再使用的。</p><p><strong>优点</strong>：实现简单，判定效率高。</p><p><strong>缺点</strong>：无法解决循环引用问题。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 循环引用示例：引用计数法无法处理</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CircleReference</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> CircleReference ref;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">CircleReference</span> <span class="variable">a</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CircleReference</span>();  <span class="comment">// a 引用计数 = 1</span></span><br><span class="line">        <span class="type">CircleReference</span> <span class="variable">b</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CircleReference</span>();  <span class="comment">// b 引用计数 = 1</span></span><br><span class="line"></span><br><span class="line">        a.ref = b;  <span class="comment">// b 引用计数 = 2</span></span><br><span class="line">        b.ref = a;  <span class="comment">// a 引用计数 = 2</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 此时 a 和 b 都不再被其他对象引用（除了互相引用）</span></span><br><span class="line">        <span class="comment">// 引用计数都是 2，但实际上已经&quot;死&quot;了</span></span><br><span class="line"></span><br><span class="line">        a = <span class="literal">null</span>;  <span class="comment">// a 引用计数 = 1</span></span><br><span class="line">        b = <span class="literal">null</span>;  <span class="comment">// b 引用计数 = 1</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 虽然 a 和 b 已经不可达，但引用计数不为 0</span></span><br><span class="line">        <span class="comment">// 引用计数法无法回收这对对象！</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="2-可达性分析（JVM-使用）"><a href="#2-可达性分析（JVM-使用）" class="headerlink" title="2. 可达性分析（JVM 使用）"></a>2. 可达性分析（JVM 使用）</h4><p>通过一系列称为 “GC Roots” 的对象作为起始点，从这些节点向下搜索，搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时，说明这个对象是不可达的，可以被回收。</p><p><strong>GC Roots 包括</strong>：</p><ul><li>虚拟机栈（栈帧中的本地变量表）中引用的对象</li><li>方法区中类静态属性引用的对象</li><li>方法区中常量引用的对象</li><li>本地方法栈中 JNI（Native 方法）引用的对象</li><li>Java 虚拟机内部的引用（Class 对象、异常对象等）</li><li>所有被同步锁（synchronized）持有的对象</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GC</span> RootsDemo &#123;</span><br><span class="line">    <span class="comment">// GC Roots 1：类的静态属性引用的对象</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> GCRootsDemo instance;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// GC Roots 2：虚拟机栈中引用的对象</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">byte</span>[] data;  <span class="comment">// 占较大内存，避免被优化</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 局部变量表中的引用，作为 GC Roots</span></span><br><span class="line">        <span class="type">GCRootsDemo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GCRootsDemo</span>();  <span class="comment">// demo 是 GC Root</span></span><br><span class="line">        demo.data = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">10</span> * <span class="number">1024</span> * <span class="number">1024</span>];  <span class="comment">// 10MB</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// demo 仍然被 instance 引用，不能回收</span></span><br><span class="line">        instance = demo;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 解除 demo 引用</span></span><br><span class="line">        demo = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 此时 demo 对象只被 instance 引用</span></span><br><span class="line">        <span class="comment">// 仍然是可达的，不能被回收</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="垃圾收集算法"><a href="#垃圾收集算法" class="headerlink" title="垃圾收集算法"></a>垃圾收集算法</h3><h4 id="1-标记-清除算法（Mark-Sweep）"><a href="#1-标记-清除算法（Mark-Sweep）" class="headerlink" title="1. 标记-清除算法（Mark-Sweep）"></a>1. 标记-清除算法（Mark-Sweep）</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 标记-清除算法        A[初始状态] --> B[标记阶段]        B --> C[清除阶段]        C --> D[回收后]    end    style A fill:#e3f2fd    style D fill:#e8f5e9</pre></div><p><strong>步骤</strong>：</p><ol><li><strong>标记</strong>：遍历所有对象，标记出所有需要回收的对象</li><li><strong>清除</strong>：统一回收所有被标记的对象</li></ol><p><strong>缺点</strong>：</p><ul><li>效率不高</li><li>会产生大量内存碎片</li></ul><h4 id="2-复制算法（Copying）"><a href="#2-复制算法（Copying）" class="headerlink" title="2. 复制算法（Copying）"></a>2. 复制算法（Copying）</h4><p>将可用内存按容量划分为大小相等的两块，每次只使用其中一块。当这一块内存用完了，就将还存活的对象复制到另一块上面，然后再把已使用过的内存空间一次清理掉。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[内存区域] --> B[From 区 使用中]    A --> C[To 区 空闲]    B -->|存活对象复制| C    B -->|清空| D[From 区清空]    C -->|交换角色| E[To 变 From]    D -->|交换角色| F[From 变 To]</pre></div><p><strong>优点</strong>：实现简单，运行高效，不会产生内存碎片。</p><p><strong>缺点</strong>：可用内存缩小为原来的一半，浪费空间。</p><p><strong>应用</strong>：年轻代使用此算法，因为年轻代对象存活率低。</p><h4 id="3-标记-整理算法（Mark-Compact）"><a href="#3-标记-整理算法（Mark-Compact）" class="headerlink" title="3. 标记-整理算法（Mark-Compact）"></a>3. 标记-整理算法（Mark-Compact）</h4><p>针对老年代的特点，在标记-清除算法的基础上增加了”整理”步骤。标记过程与标记-清除算法一样，但后续不是直接清理可回收对象，而是让所有存活的对象都向一端移动，然后直接清理掉边界以外的内存。</p><p><strong>优点</strong>：不会产生内存碎片。</p><p><strong>缺点</strong>：整理过程需要移动对象，效率较低。</p><h4 id="4-分代收集算法（Generational-Collection）"><a href="#4-分代收集算法（Generational-Collection）" class="headerlink" title="4. 分代收集算法（Generational Collection）"></a>4. 分代收集算法（Generational Collection）</h4><p>当前商业 JVM 普遍采用这种算法。根据对象存活周期的不同将内存划分为几块，一般把 Java 堆分为年轻代和老年代，然后根据各年代的特点采用最适当的收集算法。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[分代收集算法] --> B[年轻代]    A --> C[老年代]    B --> B1[ Eden 区]    B --> B2[Survivor 区]    C --> C1[标记-整理算法]    B1 --> B3[复制算法]    B2 --> B3    style A fill:#fff3e0    style B fill:#e3f2fd    style C fill:#e8f5e9</pre></div><h3 id="垃圾收集器"><a href="#垃圾收集器" class="headerlink" title="垃圾收集器"></a>垃圾收集器</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 垃圾收集器        A[年轻代收集器] --> B1[Serial]        A --> B2[ParNew]        A --> B3[Parallel Scavenge]        A --> B4[G1]        A --> B5[ZGC]        A --> B6[Shenandoah]        C[老年代收集器] --> C1[Serial Old]        C --> C2[Parallel Old]        C --> C3[CMS]        C --> C4[G1]        C --> C5[ZGC]        C --> C6[Shenandoah]    end</pre></div><h4 id="Serial-收集器"><a href="#Serial-收集器" class="headerlink" title="Serial 收集器"></a>Serial 收集器</h4><p>最基本、历史最悠久的收集器。是一个单线程收集器，在进行垃圾收集时，必须暂停所有其他工作线程（Stop The World）。</p><p><strong>特点</strong>：简单高效，Client 模式下默认的年轻代收集器。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定使用 Serial 收集器</span></span><br><span class="line">-XX:+UseSerialGC</span><br></pre></td></tr></table></figure><h4 id="ParNew-收集器"><a href="#ParNew-收集器" class="headerlink" title="ParNew 收集器"></a>ParNew 收集器</h4><p>Serial 收集器的多线程版本，除了使用多线程进行垃圾收集外，其余行为与 Serial 完全一样。</p><p><strong>特点</strong>：Server 模式下首选的年轻代收集器，可以与 CMS 配合使用。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定使用 ParNew 收集器</span></span><br><span class="line">-XX:+UseParNewGC</span><br></pre></td></tr></table></figure><h4 id="Parallel-Scavenge-收集器"><a href="#Parallel-Scavenge-收集器" class="headerlink" title="Parallel Scavenge 收集器"></a>Parallel Scavenge 收集器</h4><p>关注点是吞吐量（Throughput），即吞吐量 &#x3D; 运行用户代码时间 &#x2F; (运行用户代码时间 + 垃圾收集时间)。</p><p><strong>特点</strong>：自适应调节策略，GC 自适应调节参数。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定使用 Parallel Scavenge 收集器</span></span><br><span class="line">-XX:+UseParallelGC</span><br><span class="line"><span class="comment"># 设置最大 GC 暂停时间</span></span><br><span class="line">-XX:MaxGCPauseMillis=100</span><br><span class="line"><span class="comment"># 设置吞吐量大小</span></span><br><span class="line">-XX:GCTimeRatio=99</span><br></pre></td></tr></table></figure><h4 id="CMS-收集器"><a href="#CMS-收集器" class="headerlink" title="CMS 收集器"></a>CMS 收集器</h4><p>Concurrent Mark Sweep，以获取最短回收停顿时间为目标的收集器。</p><p><strong>收集过程</strong>：</p><ol><li>初始标记（Initial Mark）：标记 GC Roots 能直接关联到的对象</li><li>并发标记（Concurrent Mark）：进行 GC Roots Tracing</li><li>重新标记（Remark）：修正并发标记期间因用户程序继续运作而导致标记产生变动</li><li>并发清除（Concurrent Sweep）：清理垃圾</li></ol><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>sequenceDiagram    participant STW as Stop The World    participant GC as CMS GC        GC->>STW: 1. 初始标记（STW）    Note over STW: 标记 GC Roots 直接关联对象    STW-->>GC: 完成        GC->>GC: 2. 并发标记（并发）    Note over GC: 遍历引用链，标记所有存活对象        GC->>STW: 3. 重新标记（STW）    Note over STW: 修正并发标记期间变动的对象    STW-->>GC: 完成        GC->>GC: 4. 并发清除（并发）    Note over GC: 清除已死亡的对象</pre></div><p><strong>缺点</strong>：</p><ul><li>对 CPU 资源敏感，会占用 CPU 资源</li><li>无法处理浮动垃圾（并发清理阶段产生的垃圾）</li><li>产生内存碎片</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定使用 CMS 收集器</span></span><br><span class="line">-XX:+UseConcMarkSweepGC</span><br><span class="line"><span class="comment"># 触发 CMS 的阈值</span></span><br><span class="line">-XX:CMSInitiatingOccupancyFraction=68</span><br></pre></td></tr></table></figure><h4 id="G1-收集器"><a href="#G1-收集器" class="headerlink" title="G1 收集器"></a>G1 收集器</h4><p>Garbage First，将整个堆划分为多个大小相等的 Region，跟踪各个 Region 里面的垃圾堆积价值（回收所获得的空间大小以及回收所需时间的经验值），在后台维护一个优先列表，每次根据允许的收集时间，优先回收价值最大的 Region。</p><p><strong>特点</strong>：</p><ul><li>并行与并发</li><li>分代收集</li><li>空间整合（不产生内存碎片）</li><li>可预测的停顿</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 指定使用 G1 收集器</span></span><br><span class="line">-XX:+UseG1GC</span><br><span class="line"><span class="comment"># 设置目标停顿时间</span></span><br><span class="line">-XX:MaxGCPauseMillis=200</span><br><span class="line"><span class="comment"># 设置 Region 大小</span></span><br><span class="line">-XX:G1HeapRegionSize=mb</span><br></pre></td></tr></table></figure><hr><h2 id="类加载机制"><a href="#类加载机制" class="headerlink" title="类加载机制"></a>类加载机制</h2><h3 id="类的生命周期"><a href="#类的生命周期" class="headerlink" title="类的生命周期"></a>类的生命周期</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[类的生命周期] --> B[加载 Loading]    B --> C[验证 Verification]    C --> D[准备 Preparation]    D --> E[解析 Resolution]    E --> F[初始化 Initialization]    F --> G[使用 Using]    G --> H[卸载 Unloading]    style A fill:#fff3e0</pre></div><h3 id="类加载的过程"><a href="#类加载的过程" class="headerlink" title="类加载的过程"></a>类加载的过程</h3><h4 id="1-加载（Loading）"><a href="#1-加载（Loading）" class="headerlink" title="1. 加载（Loading）"></a>1. 加载（Loading）</h4><p>“加载”是”类加载”过程的一个阶段，两者不可混淆。</p><p><strong>此阶段完成的事情</strong>：</p><ul><li>通过类的全限定名获取定义此类的二进制字节流</li><li>将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构</li><li>在内存中生成一个代表这个类的 java.lang.Class 对象，作为方法区这个类的各种数据的访问入口</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 类的加载：Class 对象是访问类元数据的入口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoadingDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 获取 Class 对象的方式</span></span><br><span class="line">        <span class="comment">// 方式一：Class.forName()</span></span><br><span class="line">        Class&lt;?&gt; clazz1 = Class.forName(<span class="string">&quot;java.lang.String&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式二：.class 属性</span></span><br><span class="line">        Class&lt;?&gt; clazz2 = String.class;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式三：对象的 getClass() 方法</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">        Class&lt;?&gt; clazz3 = str.getClass();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 三个 Class 对象是同一个（类的 Class 对象在 JVM 中唯一）</span></span><br><span class="line">        System.out.println(clazz1 == clazz2);  <span class="comment">// true</span></span><br><span class="line">        System.out.println(clazz2 == clazz3);  <span class="comment">// true</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="2-验证（Verification）"><a href="#2-验证（Verification）" class="headerlink" title="2. 验证（Verification）"></a>2. 验证（Verification）</h4><p>确保 Class 文件的字节流中包含的信息符合当前 JVM 要求，不会危害 JVM 安全。</p><p><strong>验证阶段包括</strong>：</p><ul><li>文件格式验证：验证字节流是否符合 Class 文件格式规范</li><li>元数据验证：对字节码描述的信息进行语义分析</li><li>字节码验证：通过数据流和控制流分析，确保程序语义的合法性</li><li>符号引用验证：确保解析动作能正常执行</li></ul><h4 id="3-准备（Preparation）"><a href="#3-准备（Preparation）" class="headerlink" title="3. 准备（Preparation）"></a>3. 准备（Preparation）</h4><p><strong>正式为类变量分配内存并设置类变量初始值的阶段</strong>，这些变量所使用的内存都将在方法区中进行分配。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PreparationDemo</span> &#123;</span><br><span class="line">    <span class="comment">// 类变量：准备阶段赋默认值</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> <span class="variable">staticVar</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 常量：准备阶段赋最终值</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">CONSTANT</span> <span class="operator">=</span> <span class="number">200</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 编译时常量在准备阶段就被替换为具体值</span></span><br><span class="line">    <span class="comment">// 因为它是 static final，编译器就知道值是多少</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>注意</strong>：</p><ul><li>这时候进行内存分配的仅包括类变量（static 修饰的变量），不包括实例变量</li><li>实例变量会在对象实例化时随对象一起分配在堆中</li><li>初始值通常是零值，而非代码中赋予的值</li></ul><table><thead><tr><th>类型</th><th>零值</th></tr></thead><tbody><tr><td>int</td><td>0</td></tr><tr><td>long</td><td>0L</td></tr><tr><td>short</td><td>(short) 0</td></tr><tr><td>byte</td><td>(byte) 0</td></tr><tr><td>char</td><td>‘\u0000’</td></tr><tr><td>boolean</td><td>false</td></tr><tr><td>reference</td><td>null</td></tr><tr><td>float</td><td>0.0f</td></tr><tr><td>double</td><td>0.0d</td></tr></tbody></table><h4 id="4-解析（Resolution）"><a href="#4-解析（Resolution）" class="headerlink" title="4. 解析（Resolution）"></a>4. 解析（Resolution）</h4><p><strong>将常量池内的符号引用替换为直接引用的过程</strong>。</p><ul><li><strong>符号引用</strong>：以一组符号来描述所引用的目标，符号可以是任何形式的字面量</li><li><strong>直接引用</strong>：直接指向目标的指针、相对偏移量或能间接定位到目标的句柄</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 解析示例</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ResolutionDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">Class</span> <span class="variable">clazz</span> <span class="operator">=</span> Class.forName(<span class="string">&quot;java.lang.String&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 获取方法或字段时，JVM 会进行解析</span></span><br><span class="line">        <span class="comment">// 符号引用 -&gt; 直接引用</span></span><br><span class="line">        java.lang.reflect.<span class="type">Field</span> <span class="variable">field</span> <span class="operator">=</span> </span><br><span class="line">            clazz.getDeclaredField(<span class="string">&quot;value&quot;</span>);</span><br><span class="line">        <span class="comment">// field 是一个直接引用，指向 actual character array</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="5-初始化（Initialization）"><a href="#5-初始化（Initialization）" class="headerlink" title="5. 初始化（Initialization）"></a>5. 初始化（Initialization）</h4><p><strong>类加载过程的最后一步</strong>，真正执行类中定义的 Java 代码。</p><p><strong>触发初始化的场景（主动引用）</strong>：</p><ol><li>遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时</li><li>使用 java.lang.reflect 包的方法对类进行反射调用时</li><li>当初始化一个类时，发现其父类还没初始化，需要先触发父类初始化</li><li>JVM 启动时，会先初始化包含 main() 方法的那个类</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InitializationDemo</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;InitializationDemo 被初始化！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 触发 InitializationDemo 初始化</span></span><br><span class="line">        System.out.println(<span class="string">&quot;main 方法执行&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 触发 A 初始化</span></span><br><span class="line">        <span class="comment">// A a = new A();  // 如果有 A 类，会触发其初始化</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;A 被初始化！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="类加载器"><a href="#类加载器" class="headerlink" title="类加载器"></a>类加载器</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[类加载器] --> B[Bootstrap ClassLoader 启动类加载器]    A --> C[Extension ClassLoader 扩展类加载器]    A --> D[Application ClassLoader 应用类加载器]    B --> C    C --> D    B -.->|最顶层| E[C++ 实现]    C -.->|Java 实现| F[ExtClassLoader]    D -.->|Java 实现| G[AppClassLoader]    style A fill:#fff3e0</pre></div><h4 id="三种默认类加载器"><a href="#三种默认类加载器" class="headerlink" title="三种默认类加载器"></a>三种默认类加载器</h4><ol><li><p><strong>Bootstrap ClassLoader（启动类加载器）</strong></p><ul><li>最顶层的类加载器</li><li>由 C++ 实现，负责加载 <code>JAVA_HOME/lib</code> 目录中的类库</li><li>无法被 Java 程序直接引用</li></ul></li><li><p><strong>Extension ClassLoader（扩展类加载器）</strong></p><ul><li>由 Java 实现（<code>ExtClassLoader</code>）</li><li>负责加载 <code>JAVA_HOME/lib/ext</code> 目录中的类库</li><li>开发者可以把自己写的类打包成 jar 放到此目录</li></ul></li><li><p><strong>Application ClassLoader（应用类加载器）</strong></p><ul><li>由 Java 实现（<code>AppClassLoader</code>）</li><li>负责加载 classpath 上指定的类库</li><li>一般情况下这是程序中默认的类加载器</li></ul></li></ol><h4 id="双亲委派模型"><a href="#双亲委派模型" class="headerlink" title="双亲委派模型"></a>双亲委派模型</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[Application ClassLoader] --> B[Extension ClassLoader]    B --> C[Bootstrap ClassLoader]    C -->|找不到类| D[向下查找]    D --> E[Extension ClassLoader]    E -->|找不到类| F[向下查找]    F --> G[Application ClassLoader]    G -->|找不到类| H[抛出 ClassNotFoundException]    style A fill:#e3f2fd    style C fill:#fff3e0</pre></div><p><strong>工作过程</strong>：如果一个类加载器收到了类加载的请求，它首先不会自己去尝试加载这个类，而是把这个请求委派给父类加载器去完成，每一层都是如此，因此所有的加载请求最终都应该传送到顶层的启动类加载器中，只有当父加载器反馈自己无法完成这个加载请求时，子加载器才会尝试自己去加载。</p><p><strong>为什么需要双亲委派模型？</strong></p><ul><li><strong>安全性</strong>：防止核心类被篡改。比如用户自己写一个 <code>java.lang.String</code> 类，由于双亲委派模型，这个类永远不会被加载，因为会优先使用父加载器加载的 <code>java.lang.String</code>。</li><li><strong>避免重复加载</strong>：父加载器已加载的类，子加载器不需要再次加载。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 自定义类加载器示例</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyClassLoader</span> <span class="keyword">extends</span> <span class="title class_">ClassLoader</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String classPath;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">MyClassLoader</span><span class="params">(String classPath)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.classPath = classPath;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> Class&lt;?&gt; findClass(String name) <span class="keyword">throws</span> ClassNotFoundException &#123;</span><br><span class="line">        <span class="type">byte</span>[] classData = loadClassData(name);</span><br><span class="line">        <span class="keyword">if</span> (classData == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">ClassNotFoundException</span>(name);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> defineClass(name, classData, <span class="number">0</span>, classData.length);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">byte</span>[] loadClassData(String className) &#123;</span><br><span class="line">        <span class="comment">// 从文件系统读取 class 文件</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">fileName</span> <span class="operator">=</span> classPath + File.separatorChar </span><br><span class="line">            + className.replace(<span class="string">&#x27;.&#x27;</span>, File.separatorChar) + <span class="string">&quot;.class&quot;</span>;</span><br><span class="line">        <span class="keyword">try</span> (<span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(fileName);</span><br><span class="line">             <span class="type">ByteArrayOutputStream</span> <span class="variable">baos</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>()) &#123;</span><br><span class="line">            <span class="type">int</span> data;</span><br><span class="line">            <span class="keyword">while</span> ((data = is.read()) != -<span class="number">1</span>) &#123;</span><br><span class="line">                baos.write(data);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> baos.toByteArray();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="并发编程"><a href="#并发编程" class="headerlink" title="并发编程"></a>并发编程</h2><h3 id="为什么要并发？"><a href="#为什么要并发？" class="headerlink" title="为什么要并发？"></a>为什么要并发？</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[单线程] --> B[CPU 空闲 等待 I/O]    A -->|I/O 操作| C[阻塞]    D[多线程] --> E[线程1 等待 I/O]    D --> F[线程2 处理业务]    style B fill:#ffcdd2    style E fill:#fff9c4    style F fill:#c8e6c9</pre></div><p><strong>单线程的问题</strong>：</p><ul><li>多核 CPU 环境下，只用一个核太浪费</li><li>I&#x2F;O 等待时 CPU 空闲，效率低</li></ul><p><strong>多线程的优势</strong>：</p><ul><li>提高 CPU 利用率</li><li>提高程序吞吐量</li><li>便于异步处理</li><li>提升用户体验</li></ul><h3 id="并发编程三大概念"><a href="#并发编程三大概念" class="headerlink" title="并发编程三大概念"></a>并发编程三大概念</h3><h4 id="1-原子性（Atomicity）"><a href="#1-原子性（Atomicity）" class="headerlink" title="1. 原子性（Atomicity）"></a>1. 原子性（Atomicity）</h4><p>一个操作或多个操作要么全部执行，要么全部不执行。</p><p><strong>示例</strong>：i++ 不是原子操作</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AtomicityDemo</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">            count++;  <span class="comment">// 这不是原子操作！</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">AtomicityDemo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicityDemo</span>();</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(demo);</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(demo);</span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">        t1.join();</span><br><span class="line">        t2.join();</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 期望：20000，实际可能小于 20000</span></span><br><span class="line">        System.out.println(<span class="string">&quot;最终结果：&quot;</span> + demo.count);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>count++</code> 实际上分为三步：</p><ol><li>读取 count 的值</li><li>将 count 加 1</li><li>写入新的 count 值</li></ol><p>多线程下可能导致数据不一致。</p><p><strong>解决方案</strong>：使用 AtomicInteger</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicInteger;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AtomicDemo</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">AtomicInteger</span> <span class="variable">count</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">AtomicInteger</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">            count.incrementAndGet();  <span class="comment">// 原子操作</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getCount</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> count.get();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="2-可见性（Visibility）"><a href="#2-可见性（Visibility）" class="headerlink" title="2. 可见性（Visibility）"></a>2. 可见性（Visibility）</h4><p>一个线程对共享变量的修改，其他线程能够立即看到。</p><p><strong>示例</strong>：可见性问题</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VisibilityDemo</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="comment">// 加上 volatile 关键字</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">boolean</span> <span class="variable">running</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (running) &#123;</span><br><span class="line">            <span class="comment">// 无限循环</span></span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">&quot;线程结束了&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stopRunning</span><span class="params">()</span> &#123;</span><br><span class="line">        running = <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">VisibilityDemo</span> <span class="variable">demo</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">VisibilityDemo</span>();</span><br><span class="line">        demo.start();</span><br><span class="line">        </span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">        demo.stopRunning();  <span class="comment">// 尝试停止线程</span></span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 如果没有 volatile，主线程修改 running 后</span></span><br><span class="line">        <span class="comment">// 子线程可能看不到（缓存问题），导致无法停止</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="3-有序性（Ordering）"><a href="#3-有序性（Ordering）" class="headerlink" title="3. 有序性（Ordering）"></a>3. 有序性（Ordering）</h4><p>程序执行的顺序按照代码的先后顺序执行。</p><p><strong>问题</strong>：编译器和处理器可能会对指令进行重排序。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 有序性问题示例</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OrderingDemo</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="variable">flag</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">writer</span><span class="params">()</span> &#123;</span><br><span class="line">        a = <span class="number">1</span>;          <span class="comment">// 1. 给 a 赋值</span></span><br><span class="line">        flag = <span class="literal">true</span>;    <span class="comment">// 2. 设置 flag</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">reader</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (flag) &#123;     <span class="comment">// 3. 读取 flag</span></span><br><span class="line">            <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> a;  <span class="comment">// 4. 读取 a</span></span><br><span class="line">            System.out.println(i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>指令重排后可能的执行顺序：</p><ol><li>flag &#x3D; true</li><li>a &#x3D; 1</li><li>读取 a（此时 a &#x3D; 1）</li><li>读取 flag（此时 flag &#x3D; true）</li></ol><p>导致 i 的值可能不是我们期望的 1。</p><h3 id="volatile-关键字"><a href="#volatile-关键字" class="headerlink" title="volatile 关键字"></a>volatile 关键字</h3><p><code>volatile</code> 是 Java 中最轻量的同步机制，它有两个作用：</p><ol><li><strong>保证可见性</strong>：被 volatile 修饰的变量，修改后会立即写回主内存，并让其他线程的缓存失效</li><li><strong>禁止指令重排序</strong>：volatile 变量操作前后的代码不能被重排序</li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VolatileDemo</span> &#123;</span><br><span class="line">    <span class="comment">// volatile 保证：每次读取都从主内存读，写完立即刷新到主内存</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">increment</span><span class="params">()</span> &#123;</span><br><span class="line">        count++;  <span class="comment">// 不是原子操作，但 volatile 保证可见性</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>volatile 的适用场景</strong>：</p><ul><li>状态标志位（如 running）</li><li>双重检查锁定（Double Checked Locking）</li><li>观察量（observer）</li></ul><p><strong>volatile 的局限性</strong>：</p><ul><li>不能保证原子性（如 count++）</li><li>不能替代 synchronized</li></ul><h3 id="synchronized-关键字"><a href="#synchronized-关键字" class="headerlink" title="synchronized 关键字"></a>synchronized 关键字</h3><p><code>synchronized</code> 是 Java 中最基础的同步机制，可以保证：</p><ul><li>原子性</li><li>可见性</li><li>有序性</li></ul><p><strong>用法</strong>：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SynchronizedDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 1. 修饰实例方法 - 锁对象本身</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">method1</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 同一时刻只有一个线程能执行这个方法</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2. 修饰静态方法 - 锁类对象</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">method2</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 同一时刻只有一个线程能执行这个方法</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3. 修饰代码块 - 锁指定对象</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method3</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (<span class="built_in">this</span>) &#123;  <span class="comment">// 锁当前对象</span></span><br><span class="line">            <span class="comment">// 同步代码</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method4</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">synchronized</span> (SynchronizedDemo.class) &#123;  <span class="comment">// 锁类对象</span></span><br><span class="line">            <span class="comment">// 同步代码</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>Synchronized 原理</strong>：</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[进入 synchronized] --> B{对象是否被占用}    B -->|否| C[获取锁 设置 Mark Word]    B -->|是| D{是否同一线程}    D -->|是| E[重入 计数器+1]    D -->|否| F[进入等待队列 阻塞]    C --> G[执行同步代码]    E --> G    G --> H{正常退出 异常退出}    H --> I[释放锁 计数器-1]    I -->|计数器=0| J[唤醒等待线程]    style C fill:#c8e6c9    style F fill:#ffcdd2</pre></div><h3 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h3><p>线程池是并发编程中最重要的组件之一，它避免了频繁创建和销毁线程的开销。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[提交任务] --> B{核心线程池 是否满}    B -->|否| C[创建新线程 执行任务]    B -->|是| D{任务队列 是否满}    D -->|否| E[任务入队等待]    D -->|是| F{最大线程数 是否满}    F -->|否| G[创建新线程 执行任务]    F -->|是| H[执行拒绝策略]    C --> I[任务执行完成]    E --> I    G --> I    style A fill:#e3f2fd    style H fill:#ffcdd2</pre></div><h4 id="线程池参数"><a href="#线程池参数" class="headerlink" title="线程池参数"></a>线程池参数</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPoolDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 七大参数</span></span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">executor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>(</span><br><span class="line">            <span class="number">2</span>,                      <span class="comment">// corePoolSize：核心线程数</span></span><br><span class="line">            <span class="number">5</span>,                      <span class="comment">// maximumPoolSize：最大线程数</span></span><br><span class="line">            <span class="number">60L</span>,                    <span class="comment">// keepAliveTime：空闲线程存活时间</span></span><br><span class="line">            TimeUnit.SECONDS,       <span class="comment">// 时间单位</span></span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">LinkedBlockingQueue</span>&lt;&gt;(<span class="number">3</span>),  <span class="comment">// workQueue：任务队列</span></span><br><span class="line">            Executors.defaultThreadFactory(),  <span class="comment">// threadFactory：线程工厂</span></span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">ThreadPoolExecutor</span>.AbortPolicy()  <span class="comment">// handler：拒绝策略</span></span><br><span class="line">        );</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 提交 8 个任务测试</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">8</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">int</span> <span class="variable">taskId</span> <span class="operator">=</span> i;</span><br><span class="line">            executor.submit(() -&gt; &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;任务 &quot;</span> + taskId + <span class="string">&quot; 由线程 &quot;</span></span><br><span class="line">                    + Thread.currentThread().getName() + <span class="string">&quot; 执行&quot;</span>);</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        executor.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="拒绝策略"><a href="#拒绝策略" class="headerlink" title="拒绝策略"></a>拒绝策略</h4><table><thead><tr><th>策略</th><th>行为</th></tr></thead><tbody><tr><td>AbortPolicy</td><td>抛出 RejectedExecutionException（默认）</td></tr><tr><td>CallerRunsPolicy</td><td>由调用者线程执行</td></tr><tr><td>DiscardPolicy</td><td>静默丢弃任务</td></tr><tr><td>DiscardOldestPolicy</td><td>丢弃队列中最老的任务</td></tr></tbody></table><h4 id="Executors-工具类创建线程池"><a href="#Executors-工具类创建线程池" class="headerlink" title="Executors 工具类创建线程池"></a>Executors 工具类创建线程池</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExecutorsDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 1. 固定线程数线程池（适合CPU密集型）</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">fixedPool</span> <span class="operator">=</span> </span><br><span class="line">            Executors.newFixedThreadPool(<span class="number">5</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 单线程线程池（保证顺序执行）</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">singlePool</span> <span class="operator">=</span> </span><br><span class="line">            Executors.newSingleThreadExecutor();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3. 缓存线程池（适合IO密集型，任务多但执行快）</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">cachedPool</span> <span class="operator">=</span> </span><br><span class="line">            Executors.newCachedThreadPool();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4. 定时线程池</span></span><br><span class="line">        <span class="type">ScheduledExecutorService</span> <span class="variable">scheduledPool</span> <span class="operator">=</span> </span><br><span class="line">            Executors.newScheduledThreadPool(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 5. 工作窃取线程池</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">workStealingPool</span> <span class="operator">=</span> </span><br><span class="line">            Executors.newWorkStealingPool();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 注意：实际生产中推荐使用 ThreadPoolExecutor</span></span><br><span class="line">        <span class="comment">// Executors 创建的线程池可能有 OOM 风险</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="JUC-并发工具类"><a href="#JUC-并发工具类" class="headerlink" title="JUC 并发工具类"></a>JUC 并发工具类</h3><h4 id="CountDownLatch"><a href="#CountDownLatch" class="headerlink" title="CountDownLatch"></a>CountDownLatch</h4><p>门闩，等待一组线程完成后再执行。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CountDownLatchDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">CountDownLatch</span> <span class="variable">latch</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CountDownLatch</span>(<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">3</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">int</span> <span class="variable">playerId</span> <span class="operator">=</span> i;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;选手 &quot;</span> + playerId + <span class="string">&quot; 准备完成&quot;</span>);</span><br><span class="line">                latch.countDown();  <span class="comment">// 完成一项准备</span></span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 等待所有选手准备完成</span></span><br><span class="line">        latch.await();</span><br><span class="line">        System.out.println(<span class="string">&quot;所有选手准备完毕，开始比赛！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="CyclicBarrier"><a href="#CyclicBarrier" class="headerlink" title="CyclicBarrier"></a>CyclicBarrier</h4><p>循环栅栏，让一组线程互相等待，达到某个点后全部放行。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CyclicBarrierDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">CyclicBarrier</span> <span class="variable">barrier</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">CyclicBarrier</span>(<span class="number">3</span>, () -&gt; &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;所有玩家都准备好了，游戏开始！&quot;</span>);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">3</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">int</span> <span class="variable">playerId</span> <span class="operator">=</span> i;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;玩家 &quot;</span> + playerId + <span class="string">&quot; 加载中...&quot;</span>);</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Thread.sleep((<span class="type">long</span>) (Math.random() * <span class="number">1000</span>));</span><br><span class="line">                    System.out.println(<span class="string">&quot;玩家 &quot;</span> + playerId + <span class="string">&quot; 准备完成，等待其他人...&quot;</span>);</span><br><span class="line">                    barrier.await();  <span class="comment">// 等待其他玩家</span></span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException | BrokenBarrierException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Semaphore"><a href="#Semaphore" class="headerlink" title="Semaphore"></a>Semaphore</h4><p>信号量，控制同时访问某个资源的线程数量。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SemaphoreDemo</span> &#123;</span><br><span class="line">    <span class="comment">// 模拟停车位，只有 3 个</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">SPOTS</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Semaphore</span> <span class="variable">semaphore</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Semaphore</span>(SPOTS);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">5</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">final</span> <span class="type">int</span> <span class="variable">carId</span> <span class="operator">=</span> i;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    semaphore.acquire();  <span class="comment">// 获取许可证</span></span><br><span class="line">                    System.out.println(<span class="string">&quot;车辆 &quot;</span> + carId + <span class="string">&quot; 进入停车场&quot;</span>);</span><br><span class="line">                    Thread.sleep((<span class="type">long</span>) (Math.random() * <span class="number">3000</span>));</span><br><span class="line">                    System.out.println(<span class="string">&quot;车辆 &quot;</span> + carId + <span class="string">&quot; 离开停车场&quot;</span>);</span><br><span class="line">                    semaphore.release();  <span class="comment">// 释放许可证</span></span><br><span class="line">                &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="ConcurrentHashMap"><a href="#ConcurrentHashMap" class="headerlink" title="ConcurrentHashMap"></a>ConcurrentHashMap</h4><p>线程安全的 HashMap，高并发场景首选。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcurrentHashMapDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        ConcurrentHashMap&lt;String, Integer&gt; map = </span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">ConcurrentHashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 常用操作</span></span><br><span class="line">        map.put(<span class="string">&quot;A&quot;</span>, <span class="number">1</span>);</span><br><span class="line">        map.putIfAbsent(<span class="string">&quot;B&quot;</span>, <span class="number">2</span>);  <span class="comment">// 不存在才插入</span></span><br><span class="line">        map.get(<span class="string">&quot;A&quot;</span>);</span><br><span class="line">        map.remove(<span class="string">&quot;A&quot;</span>);</span><br><span class="line">        map.size();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 原子操作</span></span><br><span class="line">        map.putIfAbsent(<span class="string">&quot;counter&quot;</span>, <span class="number">0</span>);</span><br><span class="line">        <span class="comment">// 原子递增</span></span><br><span class="line">        map.replace(<span class="string">&quot;counter&quot;</span>, map.get(<span class="string">&quot;counter&quot;</span>), </span><br><span class="line">            map.get(<span class="string">&quot;counter&quot;</span>) + <span class="number">1</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// Java 8+ 支持 compute 方法</span></span><br><span class="line">        map.compute(<span class="string">&quot;counter&quot;</span>, (k, v) -&gt; v == <span class="literal">null</span> ? <span class="number">1</span> : v + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// computeIfPresent：key 存在才更新</span></span><br><span class="line">        map.computeIfPresent(<span class="string">&quot;counter&quot;</span>, (k, v) -&gt; v + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// computeIfAbsent：key 不存在才添加</span></span><br><span class="line">        map.computeIfAbsent(<span class="string">&quot;newCounter&quot;</span>, k -&gt; <span class="number">10</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="集合源码解析"><a href="#集合源码解析" class="headerlink" title="集合源码解析"></a>集合源码解析</h2><h3 id="HashMap-底层实现"><a href="#HashMap-底层实现" class="headerlink" title="HashMap 底层实现"></a>HashMap 底层实现</h3><p>HashMap 是 Java 中最常用的 Map 实现，了解其源码对于深入理解数据结构至关重要。</p><h4 id="JDK-1-7-vs-JDK-1-8"><a href="#JDK-1-7-vs-JDK-1-8" class="headerlink" title="JDK 1.7 vs JDK 1.8"></a>JDK 1.7 vs JDK 1.8</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[JDK 1.7] --> B[数组 + 链表 Entry<K,V>[] table]    A --> C[头插法 可能导致死循环]    D[JDK 1.8] --> E[数组 + 链表 + 红黑树 Node<K,V>[] table]    D --> F[尾插法 避免死循环]    D --> G[链表长度>8转红黑树]    style B fill:#e3f2fd    style E fill:#c8e6c9</pre></div><h4 id="HashMap-基本结构"><a href="#HashMap-基本结构" class="headerlink" title="HashMap 基本结构"></a>HashMap 基本结构</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// HashMap 核心属性</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HashMap</span>&lt;K, V&gt; <span class="keyword">extends</span> <span class="title class_">AbstractMap</span>&lt;K, V&gt; </span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">Map</span>&lt;K, V&gt;, Cloneable, Serializable &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 默认初始容量（16）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">DEFAULT_INITIAL_CAPACITY</span> <span class="operator">=</span> <span class="number">1</span> &lt;&lt; <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 最大容量（2^30）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">MAXIMUM_CAPACITY</span> <span class="operator">=</span> <span class="number">1</span> &lt;&lt; <span class="number">30</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 负载因子（0.75，元素达到容量的75%时扩容）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">float</span> <span class="variable">DEFAULT_LOAD_FACTOR</span> <span class="operator">=</span> <span class="number">0.75f</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 树化阈值（链表转红黑树）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">TREEIFY_THRESHOLD</span> <span class="operator">=</span> <span class="number">8</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 解除树化阈值（红黑树转链表）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">UNTREEIFY_THRESHOLD</span> <span class="operator">=</span> <span class="number">6</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 最小树化容量（整个 HashMap 桶数 &gt;= 64 才允许树化）</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">MIN_TREEIFY_CAPACITY</span> <span class="operator">=</span> <span class="number">64</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 存储数据的数组</span></span><br><span class="line">    <span class="keyword">transient</span> Node&lt;K, V&gt;[] table;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 元素个数</span></span><br><span class="line">    <span class="keyword">transient</span> <span class="type">int</span> size;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="hash-方法详解"><a href="#hash-方法详解" class="headerlink" title="hash() 方法详解"></a>hash() 方法详解</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// HashMap 的 hash 算法</span></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">hash</span><span class="params">(Object key)</span> &#123;</span><br><span class="line">    <span class="type">int</span> h;</span><br><span class="line">    <span class="comment">// 扰动函数：让高位参与运算，减少碰撞</span></span><br><span class="line">    <span class="keyword">return</span> (key == <span class="literal">null</span>) ? <span class="number">0</span> : (h = key.hashCode()) ^ (h &gt;&gt;&gt; <span class="number">16</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[key.hashCode] --> B[高16位不变 低16位与高16位异或]    B --> C[让hash分布更均匀]    C --> D[计算数组下标 hash & (length-1)]    style A fill:#e3f2fd    style D fill:#c8e6c9</pre></div><p><strong>为什么用 (n-1) &amp; hash 而不是 hash % n？</strong></p><ul><li><code>n</code> 必须是 2 的幂次方（如 16）</li><li><code>n - 1</code> 的二进制是低位全为 1</li><li><code>&amp;</code> 操作比 <code>%</code> 操作快得多</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 计算桶位置</span></span><br><span class="line"><span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> hash(key) &amp; (capacity - <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 例如：capacity = 16 = 2^4，capacity - 1 = 15 = 0b1111</span></span><br><span class="line"><span class="comment">// hash(key) = 31 = 0b11111</span></span><br><span class="line"><span class="comment">// index = 0b11111 &amp; 0b1111 = 0b1111 = 15</span></span><br></pre></td></tr></table></figure><h4 id="put-方法流程"><a href="#put-方法流程" class="headerlink" title="put() 方法流程"></a>put() 方法流程</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[put(key, value)] --> B{key 是否为 null}    B -->|是| C[处理 key 为 null 的情况]    B -->|否| D[计算 hash(key)]    D --> E[计算数组下标]    E --> F{该位置是否为空}    F -->|是| G[直接插入 Node]    F -->|否| H{该位置是否是红黑树}    H -->|是| I[插入红黑树节点]    H -->|否| J{链表是否已存在该 key}    J -->|是| K[覆盖 value]    J -->|否| L[尾插法添加到链表]    L --> M{链表长度是否>8}    M -->|是| N{是否满足树化条件}    N -->|是| O[链表转为红黑树]    N -->|否| P[继续使用链表]    G --> Q[检查是否需要扩容]    I --> Q    K --> Q    O --> Q    P --> Q    Q --> R{size 是否 > threshold}    R -->|是| S[扩容 resize]    R -->|否| T[返回]    style S fill:#ffcdd2</pre></div><h4 id="扩容机制"><a href="#扩容机制" class="headerlink" title="扩容机制"></a>扩容机制</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 扩容方法</span></span><br><span class="line">Node&lt;K, V&gt;[] resize() &#123;</span><br><span class="line">    <span class="comment">// 新容量 = 旧容量 * 2</span></span><br><span class="line">    newCap = oldCap &lt;&lt; <span class="number">1</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 新阈值 = 旧阈值 * 2</span></span><br><span class="line">    newThr = oldThr &lt;&lt; <span class="number">1</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 创建新数组</span></span><br><span class="line">    Node&lt;K, V&gt;[] newTable = <span class="keyword">new</span> <span class="title class_">Node</span>[newCap];</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 迁移元素（重点）</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> <span class="number">0</span>; j &lt; oldCap; j++) &#123;</span><br><span class="line">        Node&lt;K, V&gt; e;</span><br><span class="line">        <span class="keyword">if</span> ((e = oldTab[j]) != <span class="literal">null</span>) &#123;</span><br><span class="line">            oldTab[j] = <span class="literal">null</span>;</span><br><span class="line">            <span class="keyword">if</span> (e.next == <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 只有一个节点，直接计算新位置</span></span><br><span class="line">                newTab[e.hash &amp; (newCap - <span class="number">1</span>)] = e;</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (e <span class="keyword">instanceof</span> TreeNode) &#123;</span><br><span class="line">                <span class="comment">// 红黑树拆分</span></span><br><span class="line">                ((TreeNode&lt;K, V&gt;) e).split(<span class="built_in">this</span>, newTable, j, oldCap);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// 链表拆分（JDK 1.8 尾插法）</span></span><br><span class="line">                Node&lt;K, V&gt; loHead = <span class="literal">null</span>, loTail = <span class="literal">null</span>;</span><br><span class="line">                Node&lt;K, V&gt; hiHead = <span class="literal">null</span>, hiTail = <span class="literal">null</span>;</span><br><span class="line">                Node&lt;K, V&gt; next;</span><br><span class="line">                <span class="keyword">do</span> &#123;</span><br><span class="line">                    next = e.next;</span><br><span class="line">                    <span class="comment">// 原位置节点</span></span><br><span class="line">                    <span class="keyword">if</span> ((e.hash &amp; oldCap) == <span class="number">0</span>) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (loTail == <span class="literal">null</span>) loHead = e;</span><br><span class="line">                        <span class="keyword">else</span> loTail.next = e;</span><br><span class="line">                        loTail = e;</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="comment">// 扩容后的新位置节点</span></span><br><span class="line">                        <span class="keyword">if</span> (hiTail == <span class="literal">null</span>) hiHead = e;</span><br><span class="line">                        <span class="keyword">else</span> hiTail.next = e;</span><br><span class="line">                        hiTail = e;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">while</span> ((e = next) != <span class="literal">null</span>);</span><br><span class="line">                </span><br><span class="line">                <span class="comment">// 原位置放到新数组</span></span><br><span class="line">                <span class="keyword">if</span> (loTail != <span class="literal">null</span>) &#123;</span><br><span class="line">                    loTail.next = <span class="literal">null</span>;</span><br><span class="line">                    newTab[j] = loHead;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// 新位置放到新数组</span></span><br><span class="line">                <span class="keyword">if</span> (hiTail != <span class="literal">null</span>) &#123;</span><br><span class="line">                    hiTail.next = <span class="literal">null</span>;</span><br><span class="line">                    newTab[j + oldCap] = hiHead;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> newTable;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>扩容后元素位置规律</strong>：</p><ul><li><code>(e.hash &amp; oldCap) == 0</code> → 留在原位置</li><li><code>(e.hash &amp; oldCap) != 0</code> → 移动到原位置 + oldCap</li></ul><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 扩容示意        A[oldCap=16] --> B[oldCap=32]        A --> C[元素位置不变 hash & 16 == 0]        A --> D[位置 +16 hash & 16 != 0]    end    style C fill:#c8e6c9    style D fill:#e3f2fd</pre></div><h3 id="ConcurrentHashMap-源码解析"><a href="#ConcurrentHashMap-源码解析" class="headerlink" title="ConcurrentHashMap 源码解析"></a>ConcurrentHashMap 源码解析</h3><h4 id="JDK-1-7-分段锁"><a href="#JDK-1-7-分段锁" class="headerlink" title="JDK 1.7 分段锁"></a>JDK 1.7 分段锁</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[ConcurrentHashMap] --> B[Segment[] 数组]    B --> C[Segment 继承 ReentrantLock]    C --> D[HashEntry[] table]    D --> E[链表节点]    style A fill:#fff3e0    style B fill:#e3f2fd</pre></div><p>每个 Segment 包含一个 HashEntry 数组，每个 HashEntry 是一个链表节点。并发度由 Segment 数组大小决定，默认 16。</p><h4 id="JDK-1-8-CAS-synchronized"><a href="#JDK-1-8-CAS-synchronized" class="headerlink" title="JDK 1.8 CAS + synchronized"></a>JDK 1.8 CAS + synchronized</h4><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[ConcurrentHashMap JDK 1.8] --> B[Node[] table volatile 数组]    A --> C[CAS 操作 保证原子性]    A --> D[synchronized 锁桶头节点]    C --> E[putVal]    D --> E    E --> F{是否需要初始化}    F -->|是| G[initTable CAS 保证单线程]    E --> H{key 是否存在}    H -->|是| I[覆盖 value]    H -->|否| J{链表长度>8}    J -->|是| K[转为红黑树]    J -->|否| L[尾插法]    L --> M[检查扩容]    K --> M    style A fill:#fff3e0</pre></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcurrentHashMapDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        ConcurrentHashMap&lt;String, Integer&gt; map = </span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">ConcurrentHashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// CAS + synchronized 保证了并发安全</span></span><br><span class="line">        map.put(<span class="string">&quot;A&quot;</span>, <span class="number">1</span>);</span><br><span class="line">        map.putIfAbsent(<span class="string">&quot;B&quot;</span>, <span class="number">2</span>);  <span class="comment">// CAS 操作</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 原子操作</span></span><br><span class="line">        map.putIfAbsent(<span class="string">&quot;counter&quot;</span>, <span class="number">0</span>);</span><br><span class="line">        map.put(<span class="string">&quot;counter&quot;</span>, map.get(<span class="string">&quot;counter&quot;</span>) + <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 推荐：使用 compute 原子更新</span></span><br><span class="line">        map.compute(<span class="string">&quot;counter&quot;</span>, (k, v) -&gt; v == <span class="literal">null</span> ? <span class="number">1</span> : v + <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="设计模式"><a href="#设计模式" class="headerlink" title="设计模式"></a>设计模式</h2><h3 id="设计模式分类"><a href="#设计模式分类" class="headerlink" title="设计模式分类"></a>设计模式分类</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[设计模式] --> B[创建型模式]    A --> C[结构型模式]    A --> D[行为型模式]    B --> B1[单例模式]    B --> B2[工厂模式]    B --> B3[建造者模式]    B --> B4[原型模式]    C --> C1[代理模式]    C --> C2[装饰器模式]    C --> C3[适配器模式]    C --> C4[组合模式]    D --> D1[策略模式]    D --> D2[观察者模式]    D --> D3[责任链模式]    D --> D4[模板方法模式]    style A fill:#fff3e0</pre></div><h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><p>确保一个类只有一个实例，并提供一个全局访问点。</p><h4 id="饿汉式（线程安全）"><a href="#饿汉式（线程安全）" class="headerlink" title="饿汉式（线程安全）"></a>饿汉式（线程安全）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HungrySingleton</span> &#123;</span><br><span class="line">    <span class="comment">// 类加载时就创建实例，线程安全</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">HungrySingleton</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HungrySingleton</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 私有构造函数</span></span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">HungrySingleton</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 防止反射创建多个实例</span></span><br><span class="line">        <span class="keyword">if</span> (INSTANCE != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;单例对象已存在！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> HungrySingleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> INSTANCE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="懒汉式（线程不安全）"><a href="#懒汉式（线程不安全）" class="headerlink" title="懒汉式（线程不安全）"></a>懒汉式（线程不安全）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LazySingleton</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> LazySingleton instance;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">LazySingleton</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> LazySingleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="literal">null</span>) &#123;  <span class="comment">// 线程不安全</span></span><br><span class="line">            instance = <span class="keyword">new</span> <span class="title class_">LazySingleton</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="双重检查锁定（线程安全，推荐）"><a href="#双重检查锁定（线程安全，推荐）" class="headerlink" title="双重检查锁定（线程安全，推荐）"></a>双重检查锁定（线程安全，推荐）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DoubleCheckSingleton</span> &#123;</span><br><span class="line">    <span class="comment">// volatile 防止指令重排序</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">volatile</span> DoubleCheckSingleton instance;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">DoubleCheckSingleton</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> DoubleCheckSingleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="literal">null</span>) &#123;  <span class="comment">// 第一次检查</span></span><br><span class="line">            <span class="keyword">synchronized</span> (DoubleCheckSingleton.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (instance == <span class="literal">null</span>) &#123;  <span class="comment">// 第二次检查</span></span><br><span class="line">                    instance = <span class="keyword">new</span> <span class="title class_">DoubleCheckSingleton</span>();</span><br><span class="line">                    <span class="comment">// 可能的指令重排序：</span></span><br><span class="line">                    <span class="comment">// 1. 分配内存</span></span><br><span class="line">                    <span class="comment">// 2. 调用构造函数</span></span><br><span class="line">                    <span class="comment">// 3. instance 指向内存</span></span><br><span class="line">                    <span class="comment">// volatile 防止重排序，保证 2 在 3 之前</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="静态内部类（线程安全，推荐）"><a href="#静态内部类（线程安全，推荐）" class="headerlink" title="静态内部类（线程安全，推荐）"></a>静态内部类（线程安全，推荐）</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StaticInnerClassSingleton</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">StaticInnerClassSingleton</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 静态内部类，只有在被调用时才会加载，且加载过程是线程安全的</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">SingletonHolder</span> &#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">StaticInnerClassSingleton</span> <span class="variable">INSTANCE</span> <span class="operator">=</span> </span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">StaticInnerClassSingleton</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> StaticInnerClassSingleton <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> SingletonHolder.INSTANCE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="工厂模式"><a href="#工厂模式" class="headerlink" title="工厂模式"></a>工厂模式</h3><h4 id="简单工厂"><a href="#简单工厂" class="headerlink" title="简单工厂"></a>简单工厂</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 产品接口</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">call</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体产品</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">IPhone</span> <span class="keyword">implements</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">call</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;用 iPhone 打电话&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AndroidPhone</span> <span class="keyword">implements</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">call</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;用安卓手机打电话&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 工厂</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">SimplePhoneFactory</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Phone <span class="title function_">createPhone</span><span class="params">(String type)</span> &#123;</span><br><span class="line">        <span class="keyword">switch</span> (type) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;iPhone&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">IPhone</span>();</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&quot;Android&quot;</span>:</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">AndroidPhone</span>();</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>(<span class="string">&quot;未知类型&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="工厂方法模式"><a href="#工厂方法模式" class="headerlink" title="工厂方法模式"></a>工厂方法模式</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 抽象工厂</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">PhoneFactory</span> &#123;</span><br><span class="line">    Phone <span class="title function_">createPhone</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体工厂</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">IPhoneFactory</span> <span class="keyword">implements</span> <span class="title class_">PhoneFactory</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Phone <span class="title function_">createPhone</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">IPhone</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AndroidFactory</span> <span class="keyword">implements</span> <span class="title class_">PhoneFactory</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Phone <span class="title function_">createPhone</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">AndroidPhone</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FactoryMethodDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">PhoneFactory</span> <span class="variable">factory</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IPhoneFactory</span>();</span><br><span class="line">        <span class="type">Phone</span> <span class="variable">phone</span> <span class="operator">=</span> factory.createPhone();</span><br><span class="line">        phone.call();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="抽象工厂模式"><a href="#抽象工厂模式" class="headerlink" title="抽象工厂模式"></a>抽象工厂模式</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 产品族接口</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Laptop</span> &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">call</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 苹果产品族</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MacBook</span> <span class="keyword">implements</span> <span class="title class_">Laptop</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;MacBook 显示&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">iPhone</span> <span class="keyword">implements</span> <span class="title class_">Phone</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">call</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;iPhone 打电话&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 抽象工厂</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">DeviceFactory</span> &#123;</span><br><span class="line">    Laptop <span class="title function_">createLaptop</span><span class="params">()</span>;</span><br><span class="line">    Phone <span class="title function_">createPhone</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 苹果工厂</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AppleFactory</span> <span class="keyword">implements</span> <span class="title class_">DeviceFactory</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Laptop <span class="title function_">createLaptop</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">MacBook</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Phone <span class="title function_">createPhone</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">iPhone</span>();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="策略模式"><a href="#策略模式" class="headerlink" title="策略模式"></a>策略模式</h3><p>定义一系列算法，把它们一个个封装起来，并且使它们可以相互替换。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 策略接口</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">SortStrategy</span> &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">sort</span><span class="params">(<span class="type">int</span>[] array)</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体策略：冒泡排序</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">BubbleSort</span> <span class="keyword">implements</span> <span class="title class_">SortStrategy</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sort</span><span class="params">(<span class="type">int</span>[] array)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;使用冒泡排序&quot;</span>);</span><br><span class="line">        <span class="comment">// 冒泡排序实现...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体策略：快速排序</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">QuickSort</span> <span class="keyword">implements</span> <span class="title class_">SortStrategy</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sort</span><span class="params">(<span class="type">int</span>[] array)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;使用快速排序&quot;</span>);</span><br><span class="line">        <span class="comment">// 快速排序实现...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 上下文：使用策略的对象</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Sorter</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> SortStrategy strategy;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setStrategy</span><span class="params">(SortStrategy strategy)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.strategy = strategy;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sort</span><span class="params">(<span class="type">int</span>[] array)</span> &#123;</span><br><span class="line">        strategy.sort(array);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StrategyDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">int</span>[] array = &#123;<span class="number">3</span>, <span class="number">1</span>, <span class="number">4</span>, <span class="number">1</span>, <span class="number">5</span>, <span class="number">9</span>, <span class="number">2</span>, <span class="number">6</span>&#125;;</span><br><span class="line"></span><br><span class="line">        <span class="type">Sorter</span> <span class="variable">sorter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Sorter</span>();</span><br><span class="line"></span><br><span class="line">        sorter.setStrategy(<span class="keyword">new</span> <span class="title class_">BubbleSort</span>());</span><br><span class="line">        sorter.sort(array);</span><br><span class="line"></span><br><span class="line">        sorter.setStrategy(<span class="keyword">new</span> <span class="title class_">QuickSort</span>());</span><br><span class="line">        sorter.sort(array);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="代理模式"><a href="#代理模式" class="headerlink" title="代理模式"></a>代理模式</h3><p>为其他对象提供一种代理以控制对这个对象的访问。</p><h4 id="静态代理"><a href="#静态代理" class="headerlink" title="静态代理"></a>静态代理</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接口</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">Image</span> &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 真实对象</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RealImage</span> <span class="keyword">implements</span> <span class="title class_">Image</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String filename;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">RealImage</span><span class="params">(String filename)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.filename = filename;</span><br><span class="line">        loadFromDisk();  <span class="comment">// 模拟加载</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;显示图片：&quot;</span> + filename);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">loadFromDisk</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;从磁盘加载：&quot;</span> + filename);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 代理对象</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ImageProxy</span> <span class="keyword">implements</span> <span class="title class_">Image</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> RealImage realImage;</span><br><span class="line">    <span class="keyword">private</span> String filename;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ImageProxy</span><span class="params">(String filename)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.filename = filename;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 懒加载：真正需要时才加载真实对象</span></span><br><span class="line">        <span class="keyword">if</span> (realImage == <span class="literal">null</span>) &#123;</span><br><span class="line">            realImage = <span class="keyword">new</span> <span class="title class_">RealImage</span>(filename);</span><br><span class="line">        &#125;</span><br><span class="line">        realImage.display();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProxyDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Image</span> <span class="variable">image</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ImageProxy</span>(<span class="string">&quot;photo.jpg&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 此时不会加载真实图片</span></span><br><span class="line">        System.out.println(<span class="string">&quot;图片代理已创建&quot;</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 真正显示时才加载</span></span><br><span class="line">        image.display();</span><br><span class="line">        image.display();  <span class="comment">// 第二次不需要重新加载</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="JDK-动态代理"><a href="#JDK-动态代理" class="headerlink" title="JDK 动态代理"></a>JDK 动态代理</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.lang.reflect.InvocationHandler;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Method;</span><br><span class="line"><span class="keyword">import</span> java.lang.reflect.Proxy;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JDKDynamicProxy</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">RealImage</span> <span class="variable">realImage</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RealImage</span>(<span class="string">&quot;photo.jpg&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">Image</span> <span class="variable">proxy</span> <span class="operator">=</span> (Image) Proxy.newProxyInstance(</span><br><span class="line">            RealImage.class.getClassLoader(),</span><br><span class="line">            RealImage.class.getInterfaces(),</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">InvocationHandler</span>() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, </span></span><br><span class="line"><span class="params">                        Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;前置操作&quot;</span>);</span><br><span class="line">                    <span class="type">Object</span> <span class="variable">result</span> <span class="operator">=</span> method.invoke(realImage, args);</span><br><span class="line">                    System.out.println(<span class="string">&quot;后置操作&quot;</span>);</span><br><span class="line">                    <span class="keyword">return</span> result;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        );</span><br><span class="line"></span><br><span class="line">        proxy.display();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="常用工具类"><a href="#常用工具类" class="headerlink" title="常用工具类"></a>常用工具类</h2><h3 id="StringUtils-常用方法"><a href="#StringUtils-常用方法" class="headerlink" title="StringUtils 常用方法"></a>StringUtils 常用方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StringUtilsDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;  hello world  &quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断空</span></span><br><span class="line">        StringUtils.isEmpty(str);           <span class="comment">// false（有空格）</span></span><br><span class="line">        StringUtils.isBlank(str);            <span class="comment">// false（有空格）</span></span><br><span class="line">        StringUtils.isBlank(<span class="string">&quot;&quot;</span>);             <span class="comment">// true</span></span><br><span class="line">        StringUtils.isBlank(<span class="literal">null</span>);           <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 去除空白</span></span><br><span class="line">        StringUtils.trim(str);              <span class="comment">// &quot;hello world&quot;</span></span><br><span class="line">        StringUtils.trimToNull(str);         <span class="comment">// &quot;hello world&quot;，空白返回null</span></span><br><span class="line">        StringUtils.trimToEmpty(str);        <span class="comment">// &quot;hello world&quot;，空白返回&quot;&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断相等</span></span><br><span class="line">        StringUtils.equals(<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;abc&quot;</span>);    <span class="comment">// true</span></span><br><span class="line">        StringUtils.equalsIgnoreCase(<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;ABC&quot;</span>);  <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 字符串包含</span></span><br><span class="line">        StringUtils.contains(<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;b&quot;</span>);   <span class="comment">// true</span></span><br><span class="line">        StringUtils.containsIgnoreCase(<span class="string">&quot;ABC&quot;</span>, <span class="string">&quot;b&quot;</span>);  <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 截取</span></span><br><span class="line">        StringUtils.substring(<span class="string">&quot;hello world&quot;</span>, <span class="number">6</span>);     <span class="comment">// &quot;world&quot;</span></span><br><span class="line">        StringUtils.substring(<span class="string">&quot;hello world&quot;</span>, <span class="number">0</span>, <span class="number">5</span>);  <span class="comment">// &quot;hello&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 分割</span></span><br><span class="line">        StringUtils.split(<span class="string">&quot;a,b,c&quot;</span>, <span class="string">&quot;,&quot;</span>);     <span class="comment">// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 连接</span></span><br><span class="line">        StringUtils.join([<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>], <span class="string">&quot;-&quot;</span>);  <span class="comment">// &quot;a-b-c&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 重复</span></span><br><span class="line">        StringUtils.repeat(<span class="string">&quot;ab&quot;</span>, <span class="number">3</span>);         <span class="comment">// &quot;ababab&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 反转</span></span><br><span class="line">        StringUtils.reverse(<span class="string">&quot;hello&quot;</span>);        <span class="comment">// &quot;olleh&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 大小写</span></span><br><span class="line">        StringUtils.upperCase(<span class="string">&quot;hello&quot;</span>);      <span class="comment">// &quot;HELLO&quot;</span></span><br><span class="line">        StringUtils.lowerCase(<span class="string">&quot;HELLO&quot;</span>);      <span class="comment">// &quot;hello&quot;</span></span><br><span class="line">        StringUtils.capitalize(<span class="string">&quot;hello&quot;</span>);    <span class="comment">// &quot;Hello&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="CollectionUtils-常用方法"><a href="#CollectionUtils-常用方法" class="headerlink" title="CollectionUtils 常用方法"></a>CollectionUtils 常用方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.apache.commons.collections4.CollectionUtils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CollectionUtilsDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        List&lt;String&gt; list1 = Arrays.asList(<span class="string">&quot;A&quot;</span>, <span class="string">&quot;B&quot;</span>, <span class="string">&quot;C&quot;</span>);</span><br><span class="line">        List&lt;String&gt; list2 = Arrays.asList(<span class="string">&quot;B&quot;</span>, <span class="string">&quot;C&quot;</span>, <span class="string">&quot;D&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断空</span></span><br><span class="line">        CollectionUtils.isEmpty(list1);     <span class="comment">// false</span></span><br><span class="line">        CollectionUtils.isNotEmpty(list1);  <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 交集</span></span><br><span class="line">        List&lt;String&gt; intersection = </span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;(CollectionUtils.intersection(list1, list2));</span><br><span class="line">        <span class="comment">// [B, C]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 并集</span></span><br><span class="line">        CollectionUtils.union(list1, list2);</span><br><span class="line">        <span class="comment">// [A, B, C, D]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 差集（list1 - list2）</span></span><br><span class="line">        CollectionUtils.subtract(list1, list2);</span><br><span class="line">        <span class="comment">// [A]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断是否有交集</span></span><br><span class="line">        CollectionUtils.containsAny(list1, list2);  <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 过滤</span></span><br><span class="line">        List&lt;String&gt; filtered = list1.stream()</span><br><span class="line">            .filter(s -&gt; s.equals(<span class="string">&quot;A&quot;</span>))</span><br><span class="line">            .collect(Collectors.toList());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判空并赋值默认值</span></span><br><span class="line">        List&lt;String&gt; safeList = </span><br><span class="line">            CollectionUtils.isEmpty(list1) ? Collections.emptyList() : list1;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Objects-常用方法"><a href="#Objects-常用方法" class="headerlink" title="Objects 常用方法"></a>Objects 常用方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Objects;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ObjectsDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 判断相等</span></span><br><span class="line">        Objects.equals(<span class="string">&quot;abc&quot;</span>, <span class="string">&quot;abc&quot;</span>);       <span class="comment">// true</span></span><br><span class="line">        Objects.equals(<span class="literal">null</span>, <span class="string">&quot;abc&quot;</span>);        <span class="comment">// false</span></span><br><span class="line">        Objects.equals(<span class="literal">null</span>, <span class="literal">null</span>);         <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断是否为 null</span></span><br><span class="line">        Objects.isNull(<span class="literal">null</span>);               <span class="comment">// true</span></span><br><span class="line">        Objects.nonNull(<span class="literal">null</span>);              <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// requireNonNull：参数校验</span></span><br><span class="line">        <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method</span><span class="params">(String param)</span> &#123;</span><br><span class="line">            <span class="comment">// param 为 null 时抛出 NullPointerException</span></span><br><span class="line">            Objects.requireNonNull(param, <span class="string">&quot;参数不能为空&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// toString 安全版本</span></span><br><span class="line">        Objects.toString(<span class="literal">null</span>);             <span class="comment">// &quot;null&quot;</span></span><br><span class="line">        Objects.toString(<span class="literal">null</span>, <span class="string">&quot;默认值&quot;</span>);   <span class="comment">// &quot;默认值&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// hashCode（对 null 返回 0）</span></span><br><span class="line">        Objects.hashCode(<span class="literal">null</span>);             <span class="comment">// 0</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Optional-最佳实践"><a href="#Optional-最佳实践" class="headerlink" title="Optional 最佳实践"></a>Optional 最佳实践</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Optional;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OptionalDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 创建 Optional</span></span><br><span class="line">        Optional&lt;String&gt; empty = Optional.empty();</span><br><span class="line">        Optional&lt;String&gt; of = Optional.of(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">        Optional&lt;String&gt; nullable = Optional.ofNullable(<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断并获取</span></span><br><span class="line">        of.isPresent();                      <span class="comment">// true</span></span><br><span class="line">        of.isEmpty();                        <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 获取值（可能抛异常）</span></span><br><span class="line">        of.get();                           <span class="comment">// &quot;hello&quot;</span></span><br><span class="line">        <span class="comment">// nullable.get();                  // NoSuchElementException</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 获取值或默认值</span></span><br><span class="line">        nullable.orElse(<span class="string">&quot;default&quot;</span>);         <span class="comment">// &quot;default&quot;</span></span><br><span class="line">        nullable.orElseGet(() -&gt; <span class="string">&quot;computed&quot;</span>);  <span class="comment">// &quot;computed&quot;</span></span><br><span class="line">        <span class="comment">// nullable.orElseThrow();          // NoSuchElementException</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ifPresent</span></span><br><span class="line">        of.ifPresent(System.out::println);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// map 转换</span></span><br><span class="line">        of.map(String::toUpperCase);         <span class="comment">// Optional[&quot;HELLO&quot;]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// flatMap（返回 Optional）</span></span><br><span class="line">        of.flatMap(s -&gt; Optional.of(s.trim()));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// filter 过滤</span></span><br><span class="line">        of.filter(s -&gt; s.length() &gt; <span class="number">3</span>);     <span class="comment">// Optional[&quot;hello&quot;]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 链式调用</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> Optional.ofNullable(user)</span><br><span class="line">            .map(User::getName)</span><br><span class="line">            .map(String::toUpperCase)</span><br><span class="line">            .orElse(<span class="string">&quot;匿名&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="📌-总结"><a href="#📌-总结" class="headerlink" title="📌 总结"></a>📌 总结</h2><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>mindmap  root((Java 进阶))    JVM      内存模型        程序计数器        虚拟机栈        本地方法栈        堆        方法区      垃圾回收        标记-清除        复制算法        标记-整理        分代收集      类加载        双亲委派        自定义加载器    并发编程      三大概念        原子性        可见性        有序性      volatile      synchronized      线程池      JUC 工具类    集合源码      HashMap      ConcurrentHashMap    设计模式      单例      工厂      策略      代理</pre></div><h3 id="进阶学习建议"><a href="#进阶学习建议" class="headerlink" title="进阶学习建议"></a>进阶学习建议</h3><ol><li><strong>多读源码</strong>：JDK 源码、Spring 源码、MyBatis 源码</li><li><strong>手写实现</strong>：自己实现一遍 HashMap、线程池等</li><li><strong>性能调优</strong>：学习 JVM 调优、SQL 调优</li><li><strong>分布式</strong>：学习 Redis、RocketMQ、Kafka</li><li><strong>微服务</strong>：Spring Cloud、Dubbo、Service Mesh</li></ol><blockquote><p>向下扎根，向上生长 🌱</p></blockquote><hr><p><em>📅 本文首次发布于 2026 年 5 月 20 日</em></p>]]>
    </content>
    <id>https://blog.codenav.top/java-advanced/</id>
    <link href="https://blog.codenav.top/java-advanced/"/>
    <published>2026-05-20T02:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="Java-进阶核心知识点总结-🚀"><a href="#Java-进阶核心知识点总结-🚀" class="headerlink" title="Java 进阶核心知识点总结 🚀"></a>Java 进阶核心知识点总结 🚀</h1><blockquote>]]>
    </summary>
    <title>Java 进阶核心知识点总结</title>
    <updated>2026-05-20T04:21:07.797Z</updated>
  </entry>
  <entry>
    <author>
      <name>一个旅人</name>
    </author>
    <content>
      <![CDATA[<h1 id="你好，欢迎来到旅人小站-👋"><a href="#你好，欢迎来到旅人小站-👋" class="headerlink" title="你好，欢迎来到旅人小站 👋"></a>你好，欢迎来到旅人小站 👋</h1><p>你好！我是<strong>旅人</strong>，一名热爱技术的程序员。</p><p>这个博客从零开始搭建，记录我在编程道路上的学习心得、踩坑经历和成长轨迹。如果你恰好路过，希望能给你带来一点点帮助。</p><hr><h2 id="🏠-关于这个博客"><a href="#🏠-关于这个博客" class="headerlink" title="🏠 关于这个博客"></a>🏠 关于这个博客</h2><p>这是一个用 <strong>Hexo + Butterfly</strong> 主题搭建的个人技术博客，托管在 GitHub Pages 上。选择这个方案是因为：</p><ul><li>✅ 纯静态站点，访问速度快</li><li>✅ Markdown 写作，专注内容</li><li>✅ 主题美观，配置灵活</li><li>✅ 免费托管，省心省力</li></ul><h3 id="为什么建站？"><a href="#为什么建站？" class="headerlink" title="为什么建站？"></a>为什么建站？</h3><ul><li><strong>沉淀知识</strong>：看过的东西容易忘，写下来才能真正变成自己的</li><li><strong>锻炼写作</strong>：技术文档能力很重要，博客是个好练习场</li><li><strong>分享交流</strong>：如果碰巧能帮到别人，那更是意外惊喜</li><li><strong>个人品牌</strong>：慢慢积累，建立自己的技术影响力</li></ul><h3 id="建站目的"><a href="#建站目的" class="headerlink" title="建站目的"></a>建站目的</h3><ol><li>📝 记录学习过程，方便日后回顾</li><li>📚 整理知识体系，把零散的内容系统化</li><li>🤝 分享实用技术，帮助有需要的人</li><li>🌱 结交志同道合的朋友，一起进步</li></ol><hr><h2 id="🛠️-我的技术栈"><a href="#🛠️-我的技术栈" class="headerlink" title="🛠️ 我的技术栈"></a>🛠️ 我的技术栈</h2><h3 id="Java-后端"><a href="#Java-后端" class="headerlink" title="Java 后端"></a>Java 后端</h3><ul><li>Java 核心基础：集合、多线程、I&#x2F;O、反射、泛型</li><li>JVM 内存模型、类加载机制、性能调优</li><li>Spring Boot、Spring MVC、Spring Cloud 微服务开发</li><li>Spring Security 权限控制</li><li>MyBatis &#x2F; MyBatis-Plus 数据持久层</li></ul><h3 id="前端技术"><a href="#前端技术" class="headerlink" title="前端技术"></a>前端技术</h3><ul><li>HTML、CSS、JavaScript 基础</li><li>Vue、React 框架入门</li><li>Element-Plus、Vant、Ant Design 等组件库</li><li>可进行简单项目开发</li></ul><h3 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h3><table><thead><tr><th>类型</th><th>技能</th></tr></thead><tbody><tr><td>MySQL</td><td>索引优化、事务隔离级别、SQL 调优</td></tr><tr><td>Redis</td><td>缓存、分布式锁、会话管理</td></tr><tr><td>MongoDB</td><td>非关系型数据库基本使用</td></tr></tbody></table><h3 id="中间件与-DevOps"><a href="#中间件与-DevOps" class="headerlink" title="中间件与 DevOps"></a>中间件与 DevOps</h3><ul><li><strong>消息队列</strong>：RabbitMQ &#x2F; Kafka</li><li><strong>服务注册</strong>：Nacos &#x2F; Eureka，OpenFeign 服务调用</li><li><strong>分布式事务</strong>：了解 Seata 基本概念</li><li><strong>容器化</strong>：Docker</li><li><strong>版本控制</strong>：Git</li><li><strong>项目构建</strong>：Maven</li><li><strong>AI 辅助</strong>：Cursor、Claude AI 等工具</li></ul><blockquote><p>详情可以看看 <a href="/about/">关于我</a> 页面 👈</p></blockquote><hr><h2 id="📌-内容规划"><a href="#📌-内容规划" class="headerlink" title="📌 内容规划"></a>📌 内容规划</h2><p>接下来的文章会覆盖但不限于：</p><h3 id="后端开发"><a href="#后端开发" class="headerlink" title="后端开发"></a>后端开发</h3><ul><li>Java 核心技术深度解析</li><li>Spring 全家桶实战经验</li><li>微服务架构设计思路</li><li>性能调优与问题排查</li></ul><h3 id="数据库-1"><a href="#数据库-1" class="headerlink" title="数据库"></a>数据库</h3><ul><li>MySQL 进阶：索引、事务、优化</li><li>Redis 深入：缓存策略、分布式场景</li><li>NoSQL 实践：MongoDB 的使用</li></ul><h3 id="前端笔记"><a href="#前端笔记" class="headerlink" title="前端笔记"></a>前端笔记</h3><ul><li>前端基础巩固</li><li>Vue3 响应式原理探索</li><li>组件库使用技巧</li></ul><h3 id="工具效率"><a href="#工具效率" class="headerlink" title="工具效率"></a>工具效率</h3><ul><li>Git 高级操作</li><li>Docker 容器化部署</li><li>AI 编程工具使用心得</li></ul><h3 id="踩坑记录"><a href="#踩坑记录" class="headerlink" title="踩坑记录"></a>踩坑记录</h3><ul><li>开发过程中遇到的问题与解决方案</li><li>少走弯路的经验分享</li></ul><hr><h2 id="💭-我的学习态度"><a href="#💭-我的学习态度" class="headerlink" title="💭 我的学习态度"></a>💭 我的学习态度</h2><p>学习这件事，<strong>没有捷径，只有积累</strong>。</p><p>看视频觉得懂了，听讲解觉得会了，但真正掌握还是在动手实践的时候。所以这个博客更像是我的<strong>笔记本</strong>，记录真实遇到的问题和解决方法，而不是复制粘贴的笔记。</p><blockquote><p>眼过千遍不如手过一遍 🚀</p></blockquote><hr><h2 id="🎯-写作原则"><a href="#🎯-写作原则" class="headerlink" title="🎯 写作原则"></a>🎯 写作原则</h2><ul><li>✍️ 内容为王，写有价值的文章</li><li>🔍 拒绝水文，每篇都有干货</li><li>🐛 真实踩坑，不纸上谈兵</li><li>📈 持续更新，保持内容新鲜</li></ul><hr><h2 id="💬-写在最后"><a href="#💬-写在最后" class="headerlink" title="💬 写在最后"></a>💬 写在最后</h2><blockquote><p>“Talk is cheap, show me the code.”</p><p>— Linus Torvalds</p></blockquote><p>代码是最好的语言。希望这个博客能见证我的成长，也希望能和你一起进步。</p><p>如果有疑问或建议，欢迎留言交流！期待与各位技术同好切磋~</p><hr><p><em>📅 博客建于 2026 年 5 月</em></p>]]>
    </content>
    <id>https://blog.codenav.top/hello-world/</id>
    <link href="https://blog.codenav.top/hello-world/"/>
    <published>2026-05-20T01:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="你好，欢迎来到旅人小站-👋"><a href="#你好，欢迎来到旅人小站-👋" class="headerlink" title="你好，欢迎来到旅人小站 👋"></a>你好，欢迎来到旅人小站 👋</h1><p>你好！我是<strong>旅人</stron]]>
    </summary>
    <title>你好，欢迎来到旅人小站</title>
    <updated>2026-05-20T00:25:28.977Z</updated>
  </entry>
  <entry>
    <author>
      <name>一个旅人</name>
    </author>
    <category term="Java" scheme="https://blog.codenav.top/categories/Java/"/>
    <category term="Java" scheme="https://blog.codenav.top/tags/Java/"/>
    <category term="基础知识" scheme="https://blog.codenav.top/tags/%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/"/>
    <content>
      <![CDATA[<h1 id="Java-基础核心总结-📚"><a href="#Java-基础核心总结-📚" class="headerlink" title="Java 基础核心总结 📚"></a>Java 基础核心总结 📚</h1><blockquote><p>Java 是一门面向对象的编程语言，由 Sun 公司于 1995 年发布。它具有<strong>跨平台</strong>（一次编写，到处运行）、<strong>安全性高</strong>（没有指针，垃圾自动回收）、<strong>生态丰富</strong>（开源框架众多）等特点。本文将系统总结 Java 基础知识体系，帮助大家巩固核心概念，建立完整的知识框架。</p></blockquote><hr><h2 id="📖-目录"><a href="#📖-目录" class="headerlink" title="📖 目录"></a>📖 目录</h2><ol><li><a href="#java-%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B">Java 程序运行流程</a></li><li><a href="#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B">数据类型</a></li><li><a href="#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%9F%BA%E7%A1%80">面向对象基础</a></li><li><a href="#%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6">集合框架</a></li><li><a href="#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%9F%BA%E7%A1%80">多线程基础</a></li><li><a href="#io-%E6%B5%81">I&#x2F;O 流</a></li><li><a href="#%E6%B3%9B%E5%9E%8B">泛型</a></li><li><a href="#%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6">反射机制</a></li></ol><hr><h2 id="Java-程序运行流程"><a href="#Java-程序运行流程" class="headerlink" title="Java 程序运行流程"></a>Java 程序运行流程</h2><h3 id="什么是字节码？"><a href="#什么是字节码？" class="headerlink" title="什么是字节码？"></a>什么是字节码？</h3><p>Java 代码最终不会直接编译成机器码，而是编译成一种中间形式的字节码（.class 文件）。这种字节码不能被任何操作系统直接执行，但可以被 Java 虚拟机（JVM）解释执行或即时编译（JIT）成机器码。</p><p>这样做的好处是：<strong>同一个 .class 文件可以在任何安装了 JVM 的操作系统上运行</strong>，这正是 Java 跨平台的核心原理。</p><h3 id="整体执行流程"><a href="#整体执行流程" class="headerlink" title="整体执行流程"></a>整体执行流程</h3><p>Java 程序的执行流程如下：</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[.java 源文件] --> B[JavaC 编译]    B --> C[.class 字节码文件]    C --> D[类加载器 ClassLoader]    D --> E[字节码验证器]    E --> F[JVM 执行引擎]    F --> G[操作系统平台]    G --> H[硬件]    style A fill:#e1f5ff    style C fill:#fff3e0    style H fill:#e8f5e9</pre></div><h3 id="各阶段详细说明"><a href="#各阶段详细说明" class="headerlink" title="各阶段详细说明"></a>各阶段详细说明</h3><table><thead><tr><th>阶段</th><th>组件</th><th>具体做什么</th></tr></thead><tbody><tr><td><strong>编写</strong></td><td>开发者</td><td>编写 .java 源文件</td></tr><tr><td><strong>编译</strong></td><td>JavaC</td><td>将 .java 翻译成 .class 字节码</td></tr><tr><td><strong>加载</strong></td><td>ClassLoader</td><td>把 .class 文件加载到内存中</td></tr><tr><td><strong>验证</strong></td><td>字节码验证器</td><td>检查字节码是否符合 JVM 规范</td></tr><tr><td><strong>执行</strong></td><td>JVM 执行引擎</td><td>解释执行或 JIT 编译执行</td></tr><tr><td><strong>运行</strong></td><td>OS + Hardware</td><td>最终在具体硬件上运行</td></tr></tbody></table><h3 id="JVM-内存划分简介"><a href="#JVM-内存划分简介" class="headerlink" title="JVM 内存划分简介"></a>JVM 内存划分简介</h3><p>JVM 在执行程序时，会把内存划分成几个区域来管理不同类型的数据：</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[JVM 内存划分] --> B[堆 Heap]    A --> C[栈 Stack]    A --> D[方法区 Method Area]    A --> E[本地方法栈 Native Stack]    A --> F[程序计数器 PC]    B --> B1[对象实例]    B --> B2[数组]    C --> C1[方法调用]    C --> C2[局部变量]    C --> C3[操作数栈]    D --> D1[类信息]    D --> D2[常量池]    D --> D3[静态变量]    style B fill:#e8f5e9    style C fill:#e3f2fd    style D fill:#fff3e0</pre></div><h3 id="第一个-Java-程序"><a href="#第一个-Java-程序" class="headerlink" title="第一个 Java 程序"></a>第一个 Java 程序</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;Hello, Java!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>代码解析：</strong></p><ul><li><code>public class HelloWorld</code> — 定义一个公开的类，类名必须与文件名相同</li><li><code>public static void main(String[] args)</code> — 程序入口方法，JVM 从这里开始执行</li><li><code>System.out.println(...)</code> — 向控制台输出内容并换行</li></ul><p>将上述代码保存为 <code>HelloWorld.java</code>，在命令行执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">javac HelloWorld.java   <span class="comment"># 编译</span></span><br><span class="line">java HelloWorld         <span class="comment"># 运行</span></span><br></pre></td></tr></table></figure><hr><h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><h3 id="为什么需要数据类型？"><a href="#为什么需要数据类型？" class="headerlink" title="为什么需要数据类型？"></a>为什么需要数据类型？</h3><p>计算机内存中存储的是二进制数据，但不同类型的数据占用的空间不同、表示的意义也不同。<strong>数据类型就是对数据的一种分类，告诉 JVM 应该以什么方式存储和处理这些数据。</strong></p><p>Java 中的数据类型分为两大类：<strong>基本数据类型</strong>和<strong>引用数据类型</strong>。基本数据类型存储的是具体的值，而引用数据类型存储的是对象在内存中的地址（引用）。</p><h3 id="两大类型分类"><a href="#两大类型分类" class="headerlink" title="两大类型分类"></a>两大类型分类</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    subgraph 数据类型        A[数据类型] --> B[基本数据类型]        A --> C[引用数据类型]        B --> B1[整型]        B --> B2[浮点型]        B --> B3[字符型]        B --> B4[布尔型]        C --> C1[类]        C --> C2[接口]        C --> C3[数组]    end    style A fill:#fff3e0    style B fill:#e3f2fd    style C fill:#e8f5e9</pre></div><h3 id="基本数据类型（8种）"><a href="#基本数据类型（8种）" class="headerlink" title="基本数据类型（8种）"></a>基本数据类型（8种）</h3><p>Java 定义了 8 种基本数据类型，它们是 Java 语言的基础组成部分。</p><table><thead><tr><th>类型</th><th>关键字</th><th>占用空间</th><th>取值范围</th><th>默认值</th><th>示例</th></tr></thead><tbody><tr><td>字节型</td><td>byte</td><td>1 字节</td><td>-128 ~ 127</td><td>0</td><td><code>byte b = 100;</code></td></tr><tr><td>短整型</td><td>short</td><td>2 字节</td><td>-32768 ~ 32767</td><td>0</td><td><code>short s = 1000;</code></td></tr><tr><td>整型</td><td>int</td><td>4 字节</td><td>-2³¹ ~ 2³¹-1（约21亿）</td><td>0</td><td><code>int i = 100000;</code></td></tr><tr><td>长整型</td><td>long</td><td>8 字节</td><td>-2⁶³ ~ 2⁶³-1</td><td>0L</td><td><code>long l = 1000000L;</code></td></tr><tr><td>单精度浮点</td><td>float</td><td>4 字节</td><td>IEEE 754 标准</td><td>0.0f</td><td><code>float f = 3.14f;</code></td></tr><tr><td>双精度浮点</td><td>double</td><td>8 字节</td><td>IEEE 754 标准</td><td>0.0d</td><td><code>double d = 3.14159;</code></td></tr><tr><td>字符型</td><td>char</td><td>2 字节</td><td>Unicode 0 ~ 65535</td><td>‘\u0000’</td><td><code>char c = &#39;A&#39;;</code></td></tr><tr><td>布尔型</td><td>boolean</td><td>1&#x2F;4 字节</td><td>true &#x2F; false</td><td>false</td><td><code>boolean flag = true;</code></td></tr></tbody></table><h3 id="使用建议"><a href="#使用建议" class="headerlink" title="使用建议"></a>使用建议</h3><ul><li>**整数类型优先使用 <code>int</code>**，如果数值可能超过 21 亿才用 <code>long</code></li><li>**浮点类型优先使用 <code>double</code>**，因为 <code>float</code> 精度较低</li><li><strong><code>long</code> 类型数字字面量必须加 <code>L</code> 后缀</strong>，否则会当作 int 处理</li><li><strong><code>float</code> 类型数字字面量必须加 <code>f</code> 后缀</strong>，否则会当作 double 处理</li></ul><h3 id="类型转换详解"><a href="#类型转换详解" class="headerlink" title="类型转换详解"></a>类型转换详解</h3><p><strong>自动类型转换（隐式转换）</strong>：容量小的类型可以自动转换为容量大的类型。</p><p>转换顺序如下：</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[byte] --> B[short]    B --> C[int]    C --> D[long]    D --> E[float]    E --> F[double]    A --> G[char]    G --> C    style A fill:#e3f2fd    style F fill:#e8f5e9</pre></div><p><strong>强制类型转换（显式转换）</strong>：容量大的类型需要强制转换，可能丢失精度。</p><h3 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DataTypes</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ============ 整型 ============</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">age</span> <span class="operator">=</span> <span class="number">25</span>;                    <span class="comment">// 普通整数，默认 int 类型</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">population</span> <span class="operator">=</span> <span class="number">7800000000L</span>;   <span class="comment">// 超大整数必须加 L</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 浮点型 ============</span></span><br><span class="line">        <span class="type">double</span> <span class="variable">pi</span> <span class="operator">=</span> <span class="number">3.1415926</span>;           <span class="comment">// double 是 Java 浮点型的默认类型</span></span><br><span class="line">        <span class="type">float</span> <span class="variable">gravity</span> <span class="operator">=</span> <span class="number">9.8f</span>;            <span class="comment">// float 必须加 f 后缀</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 字符型 ============</span></span><br><span class="line">        <span class="type">char</span> <span class="variable">grade</span> <span class="operator">=</span> <span class="string">&#x27;A&#x27;</span>;                <span class="comment">// 单引号包裹单个字符</span></span><br><span class="line">        <span class="type">char</span> <span class="variable">chinese</span> <span class="operator">=</span> <span class="string">&#x27;\u4e2d&#x27;</span>;        <span class="comment">// Unicode 编码表示中文&quot;中&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 布尔型 ============</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">isStudent</span> <span class="operator">=</span> <span class="literal">true</span>;        <span class="comment">// true 或 false，不能用 0/1 代替</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">hasJob</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 自动类型转换 ============</span></span><br><span class="line">        <span class="type">double</span> <span class="variable">d</span> <span class="operator">=</span> age;                  <span class="comment">// int 自动转换为 double</span></span><br><span class="line">        <span class="comment">// 转换过程：int(25) -&gt; double(25.0)</span></span><br><span class="line">        System.out.println(<span class="string">&quot;自动转换：int 25 转 double = &quot;</span> + d);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 强制类型转换 ============</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> (<span class="type">int</span>) <span class="number">3.14</span>;              <span class="comment">// double 强制转为 int，小数部分丢失</span></span><br><span class="line">        System.out.println(<span class="string">&quot;强制转换：double 3.14 转 int = &quot;</span> + i);  <span class="comment">// 输出 3</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 强制转换可能丢失精度的情况</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">bigNum</span> <span class="operator">=</span> <span class="number">1000000L</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">smallNum</span> <span class="operator">=</span> (<span class="type">int</span>) bigNum;     <span class="comment">// 安全，因为 long 在 int 范围内</span></span><br><span class="line">        System.out.println(<span class="string">&quot;安全转换：&quot;</span> + smallNum);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 常见错误 ============</span></span><br><span class="line">        <span class="comment">// float f = 3.14;               // 错误！3.14 默认是 double</span></span><br><span class="line">        <span class="type">float</span> <span class="variable">f</span> <span class="operator">=</span> <span class="number">3.14f</span>;                 <span class="comment">// 正确写法</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// long l = 1000000;             // 1000000 默认是 int，可能溢出</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">l</span> <span class="operator">=</span> <span class="number">1000000L</span>;               <span class="comment">// 正确写法</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="面向对象基础"><a href="#面向对象基础" class="headerlink" title="面向对象基础"></a>面向对象基础</h2><h3 id="什么是面向对象？"><a href="#什么是面向对象？" class="headerlink" title="什么是面向对象？"></a>什么是面向对象？</h3><p><strong>面向对象（OOP - Object Oriented Programming）</strong> 是一种编程思想，它把现实世界中的事物抽象成对象，用对象之间的关系来描述问题。</p><p>与之对应的是<strong>面向过程</strong>编程，比如 C 语言，它更关注”一步一步怎么做”，而面向对象更关注”谁来做这件事”。</p><h3 id="为什么要面向对象？"><a href="#为什么要面向对象？" class="headerlink" title="为什么要面向对象？"></a>为什么要面向对象？</h3><p>想象一个场景：我们需要描述一个学生管理系统。</p><p><strong>面向过程</strong>思考方式：</p><ol><li>定义学生的学号、姓名、成绩等变量</li><li>编写函数处理学生数据：添加学生、删除学生、查询成绩</li><li>用数组或链表存储所有学生</li></ol><p><strong>面向对象</strong>思考方式：</p><ol><li>定义一个 <code>Student</code> 类，封装学号、姓名、成绩</li><li>定义一个 <code>StudentManager</code> 类，管理所有学生对象</li><li>操作变成了：<code>manager.addStudent(s1)</code>、<code>s1.getScore()</code></li></ol><p>面向对象的优势在于：<strong>代码更易维护、复用性更高、更符合人类思维习惯</strong>。</p><h3 id="面向对象三大特性"><a href="#面向对象三大特性" class="headerlink" title="面向对象三大特性"></a>面向对象三大特性</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[面向对象特性] --> B[封装 Encapsulation]    A --> C[继承 Inheritance]    A --> D[多态 Polymorphism]    B --> B1[访问修饰符]    B --> B2[getter/setter]    B --> B3[数据保护]    C --> C1[extends 关键字]    C --> C2[方法重写 @Override]    C --> C3[子类父类关系]    D --> D1[重载 Overload]    D --> D2[接口实现]    D --> D3[父类引用指向子类对象]    style A fill:#fff3e0    style B fill:#e3f2fd    style C fill:#e8f5e9    style D fill:#fce4ec</pre></div><h3 id="1-封装"><a href="#1-封装" class="headerlink" title="1. 封装"></a>1. 封装</h3><p><strong>封装</strong>是把属性和方法包装在一起，对外提供接口，隐藏内部实现细节。这就像一台电视，我们只需要知道怎么用遥控器，不需要知道内部的电路原理。</p><p>封装的两个核心要点：</p><ul><li><strong>属性私有化</strong>：用 <code>private</code> 修饰属性，不让外部直接访问</li><li><strong>提供公共方法</strong>：通过 <code>public</code> 的 getter&#x2F;setter 允许外部访问和修改</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="comment">// ============ 私有属性 ============</span></span><br><span class="line">    <span class="comment">// private 修饰符表示只能在 Person 类内部访问</span></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 构造方法 ============</span></span><br><span class="line">    <span class="comment">// 无参构造</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Person</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 有参构造</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Person</span><span class="params">(String name, <span class="type">int</span> age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="comment">// 通过 setAge 方法赋值，可以利用其中的校验逻辑</span></span><br><span class="line">        setAge(age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ Getter &amp; Setter ============</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getAge</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// setAge 方法中可以加入数据校验</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(<span class="type">int</span> age)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (age &lt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>(<span class="string">&quot;年龄不能为负数！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (age &gt; <span class="number">150</span>) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalArgumentException</span>(<span class="string">&quot;年龄不合理！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>使用示例：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">EncapsulationTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">25</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;姓名：&quot;</span> + person.getName());</span><br><span class="line">        System.out.println(<span class="string">&quot;年龄：&quot;</span> + person.getAge());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 尝试设置非法年龄</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            person.setAge(-<span class="number">5</span>);  <span class="comment">// 会抛出异常</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IllegalArgumentException e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;捕获异常：&quot;</span> + e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;最终年龄：&quot;</span> + person.getAge());  <span class="comment">// 仍是 25</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-继承"><a href="#2-继承" class="headerlink" title="2. 继承"></a>2. 继承</h3><p><strong>继承</strong>是面向对象的核心特性之一，它允许我们创建一个新类（子类）来继承另一个类（父类），子类可以复用父类的属性和方法，还可以扩展自己的功能。</p><p>为什么要继承？</p><ul><li><strong>代码复用</strong>：子类可以直接使用父类的代码</li><li><strong>建立类层次</strong>：体现类之间的”is-a”关系（比如”狗 is a 动物”）</li><li><strong>多态基础</strong>：没有继承就没有多态</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ============ 父类：动物 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Animal</span> &#123;</span><br><span class="line">    <span class="comment">// protected 修饰符：允许子类访问，但对外隐藏</span></span><br><span class="line">    <span class="keyword">protected</span> String name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Animal</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 动物都会吃，但具体吃什么由子类决定</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot; 正在吃东西...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 动物都会睡觉</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sleep</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot; 正在睡觉...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 子类：狗 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Dog</span> <span class="keyword">extends</span> <span class="title class_">Animal</span> &#123;</span><br><span class="line">    <span class="comment">// 狗类独有的属性</span></span><br><span class="line">    <span class="keyword">private</span> String breed;  <span class="comment">// 品种</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 构造方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Dog</span><span class="params">(String name, String breed)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(name);        <span class="comment">// super() 调用父类构造，必须放在第一行</span></span><br><span class="line">        <span class="built_in">this</span>.breed = breed;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重写父类的 eat 方法</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot;（品种：&quot;</span> + breed + <span class="string">&quot;）正在吃狗粮...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 狗类独有的方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">bark</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot; 汪汪叫！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Getter</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getBreed</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> breed;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 子类：猫 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Cat</span> <span class="keyword">extends</span> <span class="title class_">Animal</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> indoorCat;  <span class="comment">// 是否是家猫</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Cat</span><span class="params">(String name, <span class="type">boolean</span> indoorCat)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(name);</span><br><span class="line">        <span class="built_in">this</span>.indoorCat = indoorCat;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">eat</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot; 正在吃猫粮...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 猫独有的方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">meow</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(name + <span class="string">&quot; 喵呜~&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>测试代码：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InheritanceTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Dog</span> <span class="variable">dog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;旺财&quot;</span>, <span class="string">&quot;金毛&quot;</span>);</span><br><span class="line">        <span class="type">Cat</span> <span class="variable">cat</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Cat</span>(<span class="string">&quot;咪咪&quot;</span>, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用从父类继承的方法</span></span><br><span class="line">        dog.sleep();</span><br><span class="line">        cat.sleep();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用子类重写的方法</span></span><br><span class="line">        dog.eat();   <span class="comment">// 输出：旺财（品种：金毛）正在吃狗粮...</span></span><br><span class="line">        cat.eat();   <span class="comment">// 输出：咪咪正在吃猫粮...</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用子类独有的方法</span></span><br><span class="line">        dog.bark();  <span class="comment">// 输出：旺财汪汪叫！</span></span><br><span class="line">        cat.meow();  <span class="comment">// 输出：咪咪喵呜~</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\n--- 类型信息 ---&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;dog 是 Dog 类实例：&quot;</span> + (dog <span class="keyword">instanceof</span> Dog));</span><br><span class="line">        System.out.println(<span class="string">&quot;dog 是 Animal 类实例：&quot;</span> + (dog <span class="keyword">instanceof</span> Animal));</span><br><span class="line">        System.out.println(<span class="string">&quot;dog 是 Cat 类实例：&quot;</span> + (dog <span class="keyword">instanceof</span> Cat));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-多态"><a href="#3-多态" class="headerlink" title="3. 多态"></a>3. 多态</h3><p><strong>多态</strong>是面向对象的三大特性之一，指的是同一个方法调用在不同对象上有不同的行为。多态让程序具有更好的扩展性和灵活性。</p><p>多态的两种形式：</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[多态] --> B[编译时多态 方法重载 Overload]    A --> C[运行时多态 方法重写 Override]    B --> B1[同类中方法名相同 参数列表不同]    C --> C1[父子类中方法签名相同 子类提供不同实现]    style A fill:#fff3e0</pre></div><p><strong>（1）方法重载（编译时多态）</strong></p><p>同一个类中，方法名相同但参数列表不同，编译器根据参数决定调用哪个方法。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MathHelper</span> &#123;</span><br><span class="line">    <span class="comment">// 打印整数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">(<span class="type">int</span> num)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;整数：&quot;</span> + num);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载：打印字符串</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">(String str)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;字符串：&quot;</span> + str);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载：打印小数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">(<span class="type">double</span> num)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;小数：&quot;</span> + num);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 重载：打印多个整数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">(<span class="type">int</span>... nums)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;多个整数：&quot;</span> + java.util.Arrays.toString(nums));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>（2）方法重写 + 父类引用指向子类对象（运行时多态）</strong></p><p>这是多态最典型的应用场景：父类引用可以指向子类对象，调用方法时会执行子类的实现。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PolymorphismTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ============ 向上转型 ============</span></span><br><span class="line">        <span class="comment">// 父类引用 animal 指向子类对象 dog</span></span><br><span class="line">        <span class="comment">// 这是安全的，因为 Dog is an Animal</span></span><br><span class="line">        <span class="type">Animal</span> <span class="variable">animal</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;旺财&quot;</span>, <span class="string">&quot;金毛&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 运行时多态：调用的是 Dog 重写后的 eat()</span></span><br><span class="line">        animal.eat();</span><br><span class="line">        <span class="comment">// 输出：旺财（品种：金毛）正在吃狗粮...</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// animal.sleep() 从父类继承，行为不变</span></span><br><span class="line">        animal.sleep();</span><br><span class="line">        <span class="comment">// 输出：旺财正在睡觉...</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 注意：animal 是 Animal 类型，不能调用 Dog 独有的 bark() 方法</span></span><br><span class="line">        <span class="comment">// animal.bark();  // 编译错误！</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 向下转型 ============</span></span><br><span class="line">        <span class="comment">// 向下转型需要强制转换，并且要确保类型正确</span></span><br><span class="line">        <span class="keyword">if</span> (animal <span class="keyword">instanceof</span> Dog) &#123;</span><br><span class="line">            <span class="type">Dog</span> <span class="variable">dog</span> <span class="operator">=</span> (Dog) animal;  <span class="comment">// 强制转换为 Dog 类型</span></span><br><span class="line">            dog.bark();              <span class="comment">// 现在可以调用 Dog 独有的方法了</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 使用场景：方法参数 ============</span></span><br><span class="line">        <span class="comment">// 这是一个典型的多态应用</span></span><br><span class="line">        feedAnimal(<span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;旺财&quot;</span>, <span class="string">&quot;金毛&quot;</span>));  <span class="comment">// 传入狗</span></span><br><span class="line">        feedAnimal(<span class="keyword">new</span> <span class="title class_">Cat</span>(<span class="string">&quot;咪咪&quot;</span>, <span class="literal">true</span>));   <span class="comment">// 传入猫</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 使用场景：集合 ============</span></span><br><span class="line">        List&lt;Animal&gt; animals = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        animals.add(<span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;狗1&quot;</span>, <span class="string">&quot;哈士奇&quot;</span>));</span><br><span class="line">        animals.add(<span class="keyword">new</span> <span class="title class_">Cat</span>(<span class="string">&quot;猫1&quot;</span>, <span class="literal">false</span>));</span><br><span class="line">        animals.add(<span class="keyword">new</span> <span class="title class_">Dog</span>(<span class="string">&quot;狗2&quot;</span>, <span class="string">&quot;拉布拉多&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 遍历时体现出多态</span></span><br><span class="line">        <span class="keyword">for</span> (Animal a : animals) &#123;</span><br><span class="line">            a.eat();  <span class="comment">// 每种动物吃的方式不同</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 参数类型是父类，可以接受任意子类</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">feedAnimal</span><span class="params">(Animal animal)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;开始喂食...&quot;</span>);</span><br><span class="line">        animal.eat();  <span class="comment">// 调用的是实际类型的方法</span></span><br><span class="line">        System.out.println(<span class="string">&quot;喂食完成！\n&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="集合框架"><a href="#集合框架" class="headerlink" title="集合框架"></a>集合框架</h2><h3 id="为什么需要集合？"><a href="#为什么需要集合？" class="headerlink" title="为什么需要集合？"></a>为什么需要集合？</h3><p>数组是我们最基本的数据结构，但它有两个明显的限制：</p><ol><li><strong>长度固定</strong>：创建后不能改变大小</li><li><strong>类型单一</strong>：只能存储同一种类型的数据（虽然有 Object[] 但使用不便）</li></ol><p>为了解决这些问题，Java 提供了<strong>集合框架（Collection Framework）</strong>，它是一套完善的接口和类，用于存储和操作一组对象。</p><h3 id="集合框架继承体系"><a href="#集合框架继承体系" class="headerlink" title="集合框架继承体系"></a>集合框架继承体系</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[Collection 接口] --> B[List 接口]    A --> C[Set 接口]    A --> D[Queue 接口]    B --> B1[ArrayList 实现类]    B --> B2[LinkedList 实现类]    B --> B3[Vector 实现类]    C --> C1[HashSet 实现类]    C --> C2[LinkedHashSet 实现类]    C --> C3[TreeSet 实现类]    D --> D1[PriorityQueue 实现类]    D --> D2[LinkedList 实现类]    A --> E[Map 接口]    E --> E1[HashMap 实现类]    E --> E2[LinkedHashMap 实现类]    E --> E3[TreeMap 实现类]    E --> E4[Hashtable 实现类]    style A fill:#fff3e0    style E fill:#e8f5e9    style B fill:#e3f2fd    style C fill:#fce4ec    style D fill:#fff9c4</pre></div><h3 id="List-接口-—-有序可重复"><a href="#List-接口-—-有序可重复" class="headerlink" title="List 接口 — 有序可重复"></a>List 接口 — 有序可重复</h3><p><strong>List</strong> 是一个有序的集合（也称为序列），可以精确控制每个元素的位置，通过索引访问元素，允许重复元素。</p><p><strong>ArrayList 原理</strong>：内部用数组实现，通过索引访问时非常快（O(1)），但是在中间插入或删除元素时需要移动后面所有元素，效率较低。</p><p><strong>LinkedList 原理</strong>：内部用双向链表实现，插入和删除元素很快（O(1)），但随机访问需要遍历链表，效率较低。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ListDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ============ ArrayList ============</span></span><br><span class="line">        <span class="comment">// ArrayList 是 List 接口最常用的实现类</span></span><br><span class="line">        List&lt;String&gt; arrayList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 添加元素</span></span><br><span class="line">        arrayList.add(<span class="string">&quot;Apple&quot;</span>);         <span class="comment">// 尾部添加</span></span><br><span class="line">        arrayList.add(<span class="string">&quot;Banana&quot;</span>);</span><br><span class="line">        arrayList.add(<span class="string">&quot;Orange&quot;</span>);</span><br><span class="line">        arrayList.add(<span class="number">1</span>, <span class="string">&quot;Grape&quot;</span>);      <span class="comment">// 指定索引位置插入</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;ArrayList 内容：&quot;</span> + arrayList);</span><br><span class="line">        System.out.println(<span class="string">&quot;大小：&quot;</span> + arrayList.size());</span><br><span class="line">        System.out.println(<span class="string">&quot;第二个元素（索引1）：&quot;</span> + arrayList.get(<span class="number">1</span>));</span><br><span class="line">        System.out.println(<span class="string">&quot;是否包含 Banana：&quot;</span> + arrayList.contains(<span class="string">&quot;Banana&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 修改元素</span></span><br><span class="line">        arrayList.set(<span class="number">0</span>, <span class="string">&quot;RedApple&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;修改后：&quot;</span> + arrayList);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 删除元素</span></span><br><span class="line">        arrayList.remove(<span class="string">&quot;Banana&quot;</span>);     <span class="comment">// 按内容删除</span></span><br><span class="line">        arrayList.remove(<span class="number">0</span>);             <span class="comment">// 按索引删除</span></span><br><span class="line">        System.out.println(<span class="string">&quot;删除后：&quot;</span> + arrayList);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\n--- ArrayList 适用场景 ---&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;✅ 频繁按索引访问元素&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;✅ 主要是遍历查找，少量增删&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;❌ 大量在中间位置插入/删除&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ LinkedList ============</span></span><br><span class="line">        <span class="comment">// LinkedList 同时实现了 List 和 Deque 接口</span></span><br><span class="line">        LinkedList&lt;String&gt; linkedList = <span class="keyword">new</span> <span class="title class_">LinkedList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        linkedList.add(<span class="string">&quot;First&quot;</span>);</span><br><span class="line">        linkedList.addFirst(<span class="string">&quot;Zero&quot;</span>);   <span class="comment">// 头部插入</span></span><br><span class="line">        linkedList.addLast(<span class="string">&quot;Last&quot;</span>);    <span class="comment">// 尾部插入</span></span><br><span class="line">        linkedList.add(<span class="number">2</span>, <span class="string">&quot;Middle&quot;</span>);   <span class="comment">// 中间插入</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\nLinkedList 内容：&quot;</span> + linkedList);</span><br><span class="line">        System.out.println(<span class="string">&quot;第一个：&quot;</span> + linkedList.getFirst());</span><br><span class="line">        System.out.println(<span class="string">&quot;最后一个：&quot;</span> + linkedList.getLast());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// LinkedList 作为队列使用</span></span><br><span class="line">        linkedList.poll();              <span class="comment">// 弹出头部元素</span></span><br><span class="line">        System.out.println(<span class="string">&quot;poll 后：&quot;</span> + linkedList);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\n--- LinkedList 适用场景 ---&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;✅ 频繁在头尾插入/删除&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;✅ 作为队列、栈使用&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;❌ 随机访问（按索引查找）&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Set-接口-—-无序不重复"><a href="#Set-接口-—-无序不重复" class="headerlink" title="Set 接口 — 无序不重复"></a>Set 接口 — 无序不重复</h3><p><strong>Set</strong> 是一个不包含重复元素的集合，更精确地说，Set 中不会有两个相等的元素。适合用于去重和集合运算。</p><p><strong>HashSet 原理</strong>：基于哈希表实现，元素无序，查找&#x2F;插入&#x2F;删除效率都很高（平均 O(1)）。</p><p><strong>TreeSet 原理</strong>：基于红黑树实现，元素自动排序（需要元素可比较）。</p><p><strong>LinkedHashSet 原理</strong>：基于哈希表 + 链表实现，保持元素插入顺序。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SetDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ============ HashSet ============</span></span><br><span class="line">        <span class="comment">// 最常用的 Set 实现类，无序不重复</span></span><br><span class="line">        Set&lt;String&gt; hashSet = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        hashSet.add(<span class="string">&quot;Java&quot;</span>);</span><br><span class="line">        hashSet.add(<span class="string">&quot;Python&quot;</span>);</span><br><span class="line">        hashSet.add(<span class="string">&quot;C++&quot;</span>);</span><br><span class="line">        hashSet.add(<span class="string">&quot;Java&quot;</span>);  <span class="comment">// 重复元素，不会添加成功</span></span><br><span class="line">        hashSet.add(<span class="literal">null</span>);     <span class="comment">// 可以存储一个 null</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;HashSet 大小：&quot;</span> + hashSet.size());  <span class="comment">// 4</span></span><br><span class="line">        System.out.println(<span class="string">&quot;HashSet 内容：&quot;</span> + hashSet);  <span class="comment">// 顺序可能每次不同</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否包含 Java：&quot;</span> + hashSet.contains(<span class="string">&quot;Java&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ TreeSet ============</span></span><br><span class="line">        <span class="comment">// 元素自动排序（自然顺序）</span></span><br><span class="line">        Set&lt;Integer&gt; treeSet = <span class="keyword">new</span> <span class="title class_">TreeSet</span>&lt;&gt;();</span><br><span class="line">        treeSet.add(<span class="number">30</span>);</span><br><span class="line">        treeSet.add(<span class="number">10</span>);</span><br><span class="line">        treeSet.add(<span class="number">20</span>);</span><br><span class="line">        treeSet.add(<span class="number">40</span>);</span><br><span class="line">        treeSet.add(<span class="number">25</span>);</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\nTreeSet 内容：&quot;</span> + treeSet);  <span class="comment">// [10, 20, 25, 30, 40] 自动排序</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// TreeSet 支持范围查询</span></span><br><span class="line">        System.out.println(<span class="string">&quot;小于 25 的元素：&quot;</span> + treeSet.headSet(<span class="number">25</span>));</span><br><span class="line">        System.out.println(<span class="string">&quot;大于等于 25 的元素：&quot;</span> + treeSet.tailSet(<span class="number">25</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ LinkedHashSet ============</span></span><br><span class="line">        <span class="comment">// 保持插入顺序</span></span><br><span class="line">        Set&lt;String&gt; linkedHashSet = <span class="keyword">new</span> <span class="title class_">LinkedHashSet</span>&lt;&gt;();</span><br><span class="line">        linkedHashSet.add(<span class="string">&quot;First&quot;</span>);</span><br><span class="line">        linkedHashSet.add(<span class="string">&quot;Second&quot;</span>);</span><br><span class="line">        linkedHashSet.add(<span class="string">&quot;Third&quot;</span>);</span><br><span class="line">        linkedHashSet.add(<span class="string">&quot;First&quot;</span>);  <span class="comment">// 重复，忽略</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;\nLinkedHashSet 内容：&quot;</span> + linkedHashSet);  <span class="comment">// [First, Second, Third]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 去重演示 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n--- 去重功能演示 ---&quot;</span>);</span><br><span class="line">        List&lt;String&gt; names = Arrays.asList(<span class="string">&quot;Alice&quot;</span>, <span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Alice&quot;</span>, <span class="string">&quot;Charlie&quot;</span>, <span class="string">&quot;Bob&quot;</span>);</span><br><span class="line">        Set&lt;String&gt; uniqueNames = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(names);</span><br><span class="line">        System.out.println(<span class="string">&quot;原始列表：&quot;</span> + names);</span><br><span class="line">        System.out.println(<span class="string">&quot;去重后：&quot;</span> + uniqueNames);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 集合运算 ============</span></span><br><span class="line">        Set&lt;String&gt; set1 = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(Arrays.asList(<span class="string">&quot;A&quot;</span>, <span class="string">&quot;B&quot;</span>, <span class="string">&quot;C&quot;</span>, <span class="string">&quot;D&quot;</span>));</span><br><span class="line">        Set&lt;String&gt; set2 = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(Arrays.asList(<span class="string">&quot;C&quot;</span>, <span class="string">&quot;D&quot;</span>, <span class="string">&quot;E&quot;</span>, <span class="string">&quot;F&quot;</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 并集</span></span><br><span class="line">        Set&lt;String&gt; union = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(set1);</span><br><span class="line">        union.addAll(set2);</span><br><span class="line">        System.out.println(<span class="string">&quot;\n并集：&quot;</span> + union);  <span class="comment">// [A, B, C, D, E, F]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 交集</span></span><br><span class="line">        Set&lt;String&gt; intersection = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(set1);</span><br><span class="line">        intersection.retainAll(set2);</span><br><span class="line">        System.out.println(<span class="string">&quot;交集：&quot;</span> + intersection);  <span class="comment">// [C, D]</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 差集</span></span><br><span class="line">        Set&lt;String&gt; difference = <span class="keyword">new</span> <span class="title class_">HashSet</span>&lt;&gt;(set1);</span><br><span class="line">        difference.removeAll(set2);</span><br><span class="line">        System.out.println(<span class="string">&quot;差集：&quot;</span> + difference);  <span class="comment">// [A, B]</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Map-接口-—-键值对"><a href="#Map-接口-—-键值对" class="headerlink" title="Map 接口 — 键值对"></a>Map 接口 — 键值对</h3><p><strong>Map</strong> 存储键值对（key-value）映射关系，其中 key 不能重复，每个 key 最多对应一个 value。Map 不是 Collection 的子接口，它是独立的接口家族。</p><p><strong>HashMap 原理</strong>：基于哈希表实现，key 无序，查找&#x2F;插入&#x2F;删除效率高。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MapDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ============ HashMap ============</span></span><br><span class="line">        <span class="comment">// 最常用的 Map 实现类</span></span><br><span class="line">        Map&lt;String, Integer&gt; hashMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 添加键值对</span></span><br><span class="line">        hashMap.put(<span class="string">&quot;语文&quot;</span>, <span class="number">90</span>);</span><br><span class="line">        hashMap.put(<span class="string">&quot;数学&quot;</span>, <span class="number">95</span>);</span><br><span class="line">        hashMap.put(<span class="string">&quot;英语&quot;</span>, <span class="number">88</span>);</span><br><span class="line">        hashMap.put(<span class="string">&quot;物理&quot;</span>, <span class="number">92</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// key 重复时，value 会覆盖</span></span><br><span class="line">        hashMap.put(<span class="string">&quot;数学&quot;</span>, <span class="number">100</span>);  <span class="comment">// 数学成绩更新为 100</span></span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;HashMap 内容：&quot;</span> + hashMap);</span><br><span class="line">        System.out.println(<span class="string">&quot;数学成绩：&quot;</span> + hashMap.get(<span class="string">&quot;数学&quot;</span>));     <span class="comment">// 100</span></span><br><span class="line">        System.out.println(<span class="string">&quot;化学成绩：&quot;</span> + hashMap.get(<span class="string">&quot;化学&quot;</span>));     <span class="comment">// null，不存在</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 判断操作</span></span><br><span class="line">        System.out.println(<span class="string">&quot;是否包含 key &#x27;数学&#x27;：&quot;</span> + hashMap.containsKey(<span class="string">&quot;数学&quot;</span>));</span><br><span class="line">        System.out.println(<span class="string">&quot;是否包含 value 90：&quot;</span> + hashMap.containsValue(<span class="number">90</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 删除</span></span><br><span class="line">        hashMap.remove(<span class="string">&quot;英语&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;删除后：&quot;</span> + hashMap);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 遍历方式 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n--- 遍历方式 ---&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式1：遍历 key</span></span><br><span class="line">        System.out.println(<span class="string">&quot;所有学科：&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (String subject : hashMap.keySet()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;  &quot;</span> + subject);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式2：遍历 value</span></span><br><span class="line">        System.out.println(<span class="string">&quot;所有成绩：&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Integer score : hashMap.values()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;  &quot;</span> + score);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式3：遍历键值对（最常用）</span></span><br><span class="line">        System.out.println(<span class="string">&quot;键值对：&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Map.Entry&lt;String, Integer&gt; entry : hashMap.entrySet()) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;  &quot;</span> + entry.getKey() + <span class="string">&quot; = &quot;</span> + entry.getValue());</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式4：Lambda 表达式（Java 8+）</span></span><br><span class="line">        System.out.println(<span class="string">&quot;Lambda 遍历：&quot;</span>);</span><br><span class="line">        hashMap.forEach((k, v) -&gt; System.out.println(<span class="string">&quot;  &quot;</span> + k + <span class="string">&quot; -&gt; &quot;</span> + v));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 其他 Map 实现 ============</span></span><br><span class="line">        <span class="comment">// TreeMap：按键排序</span></span><br><span class="line">        Map&lt;String, Integer&gt; treeMap = <span class="keyword">new</span> <span class="title class_">TreeMap</span>&lt;&gt;(hashMap);</span><br><span class="line">        System.out.println(<span class="string">&quot;\nTreeMap（按键排序）：&quot;</span> + treeMap);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// LinkedHashMap：保持插入顺序</span></span><br><span class="line">        Map&lt;String, Integer&gt; linkedMap = <span class="keyword">new</span> <span class="title class_">LinkedHashMap</span>&lt;&gt;();</span><br><span class="line">        linkedMap.put(<span class="string">&quot;first&quot;</span>, <span class="number">1</span>);</span><br><span class="line">        linkedMap.put(<span class="string">&quot;second&quot;</span>, <span class="number">2</span>);</span><br><span class="line">        linkedMap.put(<span class="string">&quot;third&quot;</span>, <span class="number">3</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;LinkedHashMap（保序）：&quot;</span> + linkedMap);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="各类集合对比"><a href="#各类集合对比" class="headerlink" title="各类集合对比"></a>各类集合对比</h3><table><thead><tr><th>集合类型</th><th>线程安全</th><th>底层数据结构</th><th>元素是否有序</th><th>适用场景</th></tr></thead><tbody><tr><td>ArrayList</td><td>❌ 否</td><td>数组</td><td>按索引</td><td>随机访问多，增删少</td></tr><tr><td>LinkedList</td><td>❌ 否</td><td>双向链表</td><td>按插入顺序</td><td>增删操作频繁</td></tr><tr><td>HashSet</td><td>❌ 否</td><td>哈希表</td><td>无序</td><td>去重，不关心顺序</td></tr><tr><td>LinkedHashSet</td><td>❌ 否</td><td>哈希表+链表</td><td>插入顺序</td><td>去重且需保持顺序</td></tr><tr><td>TreeSet</td><td>❌ 否</td><td>红黑树</td><td>自然排序</td><td>需要排序的去重</td></tr><tr><td>HashMap</td><td>❌ 否</td><td>哈希表</td><td>无序</td><td>键值对存储（最常用）</td></tr><tr><td>LinkedHashMap</td><td>❌ 否</td><td>哈希表+链表</td><td>插入顺序</td><td>需要按插入顺序遍历</td></tr><tr><td>TreeMap</td><td>❌ 否</td><td>红黑树</td><td>按 key 排序</td><td>需要按键排序的映射</td></tr><tr><td>Hashtable</td><td>✅ 是</td><td>哈希表</td><td>无序</td><td>旧版本，现已被 ConcurrentHashMap 取代</td></tr><tr><td>ConcurrentHashMap</td><td>✅ 是</td><td>分段锁哈希表</td><td>无序</td><td>高并发场景</td></tr></tbody></table><hr><h2 id="多线程基础"><a href="#多线程基础" class="headerlink" title="多线程基础"></a>多线程基础</h2><h3 id="什么是线程？"><a href="#什么是线程？" class="headerlink" title="什么是线程？"></a>什么是线程？</h3><p><strong>进程（Process）</strong> 是程序的一次执行过程，是系统分配资源的基本单位。每个进程都有独立的内存空间。</p><p><strong>线程（Thread）</strong> 是进程中的一个执行单元，是 CPU 调度的最小单位。一个进程可以包含多个线程，这些线程共享进程的内存空间。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[进程] --> B[内存空间 堆、方法区]    A --> C[线程1]    A --> D[线程2]    A --> E[线程3]    B --> F[共享数据]    C --> G[栈1]    D --> H[栈2]    E --> I[栈3]    style A fill:#fff3e0    style B fill:#e8f5e9    style C fill:#e3f2fd    style D fill:#e3f2fd    style E fill:#e3f2fd</pre></div><p><strong>为什么使用多线程？</strong></p><ul><li><strong>提高效率</strong>：多核 CPU 可以真正并行执行多个任务</li><li><strong>阻塞不影响</strong>：一个线程阻塞时，其他线程可以继续执行</li><li><strong>提升响应</strong>：可以将耗时操作放到后台，主线程保持响应</li></ul><h3 id="线程生命周期"><a href="#线程生命周期" class="headerlink" title="线程生命周期"></a>线程生命周期</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>stateDiagram-v2    [*] --> 新建: new Thread()    新建 --> 就绪: start() 被调用    就绪 --> 运行: 获得CPU执行权    运行 --> 就绪: yield() 时间片用完    运行 --> 阻塞: wait() sleep() join() I/O阻塞    阻塞 --> 就绪: notify() notifyAll() 时间到 join结束    运行 --> 死亡: run()执行完毕 未捕获异常    死亡 --> [*]</pre></div><p><strong>各状态说明：</strong></p><table><thead><tr><th>状态</th><th>含义</th></tr></thead><tbody><tr><td><strong>New（新建）</strong></td><td>创建了线程对象，但还没调用 start()</td></tr><tr><td><strong>Runnable（就绪）</strong></td><td>调用了 start()，等待 CPU 分配时间片</td></tr><tr><td><strong>Running（运行）</strong></td><td>获得了 CPU 执行权，正在执行 run()</td></tr><tr><td><strong>Blocked（阻塞）</strong></td><td>等待获取锁、sleep、wait 等</td></tr><tr><td><strong>Dead（死亡）</strong></td><td>run() 执行完毕或抛出未捕获异常</td></tr></tbody></table><h3 id="创建线程的方式"><a href="#创建线程的方式" class="headerlink" title="创建线程的方式"></a>创建线程的方式</h3><p>Java 中有三种创建线程的方式：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ============ 方式一：继承 Thread 类 ============</span></span><br><span class="line"><span class="comment">// 缺点：Java 是单继承，继承了 Thread 就不能再继承其他类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyThread</span> <span class="keyword">extends</span> <span class="title class_">Thread</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 线程要执行的代码</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;线程1 - 第 &quot;</span> + i + <span class="string">&quot; 次执行&quot;</span>);</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">100</span>);  <span class="comment">// 休眠 100 毫秒</span></span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 方式二：实现 Runnable 接口（推荐） ============</span></span><br><span class="line"><span class="comment">// 优点：只是实现了接口，还可以继承其他类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyRunnable</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;线程2 - 第 &quot;</span> + i + <span class="string">&quot; 次执行&quot;</span>);</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">100</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 方式三：实现 Callable 接口 + FutureTask ============</span></span><br><span class="line"><span class="comment">// 优点：有返回值，可以抛出异常，可以取消任务</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyCallable</span> <span class="keyword">implements</span> <span class="title class_">Callable</span>&lt;Integer&gt; &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt;= <span class="number">100</span>; i++) &#123;</span><br><span class="line">            sum += i;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 模拟耗时操作</span></span><br><span class="line">        Thread.sleep(<span class="number">500</span>);</span><br><span class="line">        <span class="keyword">return</span> sum;  <span class="comment">// 返回结果</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 测试类 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadCreateDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">// 方式一</span></span><br><span class="line">        <span class="type">MyThread</span> <span class="variable">thread1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MyThread</span>();</span><br><span class="line">        thread1.start();  <span class="comment">// 注意：必须调用 start()，不是 run()</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式二</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(<span class="keyword">new</span> <span class="title class_">MyRunnable</span>());</span><br><span class="line">        thread2.start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式三</span></span><br><span class="line">        FutureTask&lt;Integer&gt; futureTask = <span class="keyword">new</span> <span class="title class_">FutureTask</span>&lt;&gt;(<span class="keyword">new</span> <span class="title class_">MyCallable</span>());</span><br><span class="line">        <span class="type">Thread</span> <span class="variable">thread3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(futureTask);</span><br><span class="line">        thread3.start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 获取 Callable 的返回值</span></span><br><span class="line">        <span class="type">Integer</span> <span class="variable">result</span> <span class="operator">=</span> futureTask.get();  <span class="comment">// 会阻塞等待结果</span></span><br><span class="line">        System.out.println(<span class="string">&quot;Callable 计算结果：&quot;</span> + result);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 等待所有线程结束</span></span><br><span class="line">        thread1.join();</span><br><span class="line">        thread2.join();</span><br><span class="line">        thread3.join();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;所有线程执行完毕！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="线程同步"><a href="#线程同步" class="headerlink" title="线程同步"></a>线程同步</h3><p>多线程带来了效率的提升，但也带来了新的问题：<strong>线程安全问题</strong>。</p><p>当多个线程同时访问同一个资源（变量、文件、数据库等）时，可能会出现数据不一致的问题。</p><p><strong>经典的线程不安全问题示例：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 模拟抢票系统</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TicketSeller</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">tickets</span> <span class="operator">=</span> <span class="number">100</span>;  <span class="comment">// 100 张票</span></span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (tickets &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 模拟出票耗时</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1</span>);  <span class="comment">// 休眠 1 毫秒</span></span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 关键问题：多个线程可能同时读到 tickets &gt; 0</span></span><br><span class="line">            <span class="comment">// 导致卖出同一张票，甚至卖出负数票</span></span><br><span class="line">            System.out.println(Thread.currentThread().getName()</span><br><span class="line">                    + <span class="string">&quot; 卖出第 &quot;</span> + tickets + <span class="string">&quot; 张票&quot;</span>);</span><br><span class="line">            tickets--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">TicketSeller</span> <span class="variable">seller</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TicketSeller</span>();</span><br><span class="line">        <span class="comment">// 创建 10 个线程同时卖票</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(seller, <span class="string">&quot;窗口&quot;</span> + (i + <span class="number">1</span>)).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>解决方案：使用 synchronized 关键字</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SafeTicketSeller</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">tickets</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 同步方法：整个方法体被加锁</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">sellTicket</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (tickets &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(Thread.currentThread().getName()</span><br><span class="line">                    + <span class="string">&quot; 卖出第 &quot;</span> + tickets + <span class="string">&quot; 张票&quot;</span>);</span><br><span class="line">            tickets--;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (tickets &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            sellTicket();  <span class="comment">// 调用同步方法</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">SafeTicketSeller</span> <span class="variable">seller</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SafeTicketSeller</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> <span class="title class_">Thread</span>(seller, <span class="string">&quot;窗口&quot;</span> + (i + <span class="number">1</span>)).start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>synchronized 同步原理：</strong></p><ul><li>每个对象都有一把<strong>内部锁（Monitor Lock）</strong></li><li>当线程进入 <code>synchronized</code> 方法时，会自动获取该对象的锁</li><li>其他线程尝试进入时会被阻塞，直到锁被释放</li><li>当方法执行完毕（正常或异常），锁会自动释放</li></ul><h3 id="生产者消费者问题"><a href="#生产者消费者问题" class="headerlink" title="生产者消费者问题"></a>生产者消费者问题</h3><p>这是多线程经典问题：生产者生产数据，消费者消费数据，两者需要协调进行。</p><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[生产者] -->|放入数据| B[缓冲区]    B -->|取出数据| C[消费者]    style B fill:#fff3e0</pre></div><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProducerConsumer</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">CAPACITY</span> <span class="operator">=</span> <span class="number">10</span>;  <span class="comment">// 缓冲区容量</span></span><br><span class="line">    <span class="keyword">private</span> Queue&lt;Integer&gt; buffer = <span class="keyword">new</span> <span class="title class_">LinkedList</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 生产者方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">produce</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="keyword">while</span> (buffer.size() &gt;= CAPACITY) &#123;</span><br><span class="line">            <span class="comment">// 缓冲区满了，生产者等待</span></span><br><span class="line">            System.out.println(<span class="string">&quot;缓冲区已满，生产者等待...&quot;</span>);</span><br><span class="line">            wait();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        count++;</span><br><span class="line">        buffer.offer(count);</span><br><span class="line">        System.out.println(<span class="string">&quot;生产者放入第 &quot;</span> + count + <span class="string">&quot; 个产品&quot;</span></span><br><span class="line">                + <span class="string">&quot;，缓冲区大小：&quot;</span> + buffer.size());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 唤醒消费者</span></span><br><span class="line">        notifyAll();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 消费者方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">consume</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="keyword">while</span> (buffer.isEmpty()) &#123;</span><br><span class="line">            <span class="comment">// 缓冲区空，消费者等待</span></span><br><span class="line">            System.out.println(<span class="string">&quot;缓冲区为空，消费者等待...&quot;</span>);</span><br><span class="line">            wait();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">int</span> <span class="variable">product</span> <span class="operator">=</span> buffer.poll();</span><br><span class="line">        System.out.println(<span class="string">&quot;消费者取出第 &quot;</span> + product + <span class="string">&quot; 个产品&quot;</span></span><br><span class="line">                + <span class="string">&quot;，缓冲区大小：&quot;</span> + buffer.size());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 唤醒生产者</span></span><br><span class="line">        notifyAll();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">ProducerConsumer</span> <span class="variable">pc</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ProducerConsumer</span>();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 生产者线程</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">producer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">20</span>; i++) &#123;</span><br><span class="line">                    pc.produce();</span><br><span class="line">                    Thread.sleep((<span class="type">long</span>) (Math.random() * <span class="number">500</span>));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;, <span class="string">&quot;生产者&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 消费者线程</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">consumer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">20</span>; i++) &#123;</span><br><span class="line">                    pc.consume();</span><br><span class="line">                    Thread.sleep((<span class="type">long</span>) (Math.random() * <span class="number">800</span>));</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;, <span class="string">&quot;消费者&quot;</span>);</span><br><span class="line"></span><br><span class="line">        producer.start();</span><br><span class="line">        consumer.start();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            producer.join();</span><br><span class="line">            consumer.join();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;所有产品已处理完毕！&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="I-O-流"><a href="#I-O-流" class="headerlink" title="I&#x2F;O 流"></a>I&#x2F;O 流</h2><h3 id="什么是-I-O？"><a href="#什么是-I-O？" class="headerlink" title="什么是 I&#x2F;O？"></a>什么是 I&#x2F;O？</h3><p><strong>I&#x2F;O</strong> 是 Input&#x2F;Output 的缩写，即输入输出。在 Java 中，I&#x2F;O 用于程序与外部数据源之间的数据交换，包括：</p><ul><li><strong>读取文件</strong>（Input）</li><li><strong>写入文件</strong>（Output）</li><li><strong>网络通信</strong></li><li><strong>标准输入输出</strong></li></ul><h3 id="I-O-分类"><a href="#I-O-分类" class="headerlink" title="I&#x2F;O 分类"></a>I&#x2F;O 分类</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart TD    A[I/O 流] --> B[字节流]    A --> C[字符流]    B --> B1[InputStream 字节输入]    B --> B2[OutputStream 字节输出]    C --> C1[Reader 字符输入]    C --> C2[Writer 字符输出]    B1 --> B11[FileInputStream]    B1 --> B12[BufferedInputStream]    B1 --> B13[ObjectInputStream]    B2 --> B21[FileOutputStream]    B2 --> B22[BufferedOutputStream]    B2 --> B23[ObjectOutputStream]    C1 --> C11[FileReader]    C1 --> C12[BufferedReader]    C2 --> C21[FileWriter]    C2 --> C22[BufferedWriter]    style A fill:#fff3e0</pre></div><p><strong>何时用字节流，何时用字符流？</strong></p><ul><li><strong>字节流</strong>：用于处理二进制数据，如图片、音频、视频、压缩文件等</li><li><strong>字符流</strong>：用于处理文本数据，按字符读取，更适合处理文字</li></ul><h3 id="文件读写示例"><a href="#文件读写示例" class="headerlink" title="文件读写示例"></a>文件读写示例</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FileIODemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 字节流：复制图片 ============</span></span><br><span class="line">    <span class="comment">// 适用于二进制文件（图片、音视频等）</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">copyImage</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">source</span> <span class="operator">=</span> <span class="string">&quot;source.jpg&quot;</span>;</span><br><span class="line">        <span class="type">String</span> <span class="variable">dest</span> <span class="operator">=</span> <span class="string">&quot;dest.jpg&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="type">long</span> <span class="variable">start</span> <span class="operator">=</span> System.currentTimeMillis();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// try-with-resources：自动关闭流</span></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(source);</span><br><span class="line">             <span class="type">OutputStream</span> <span class="variable">os</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileOutputStream</span>(dest)) &#123;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 使用缓冲数组提高效率</span></span><br><span class="line">            <span class="type">byte</span>[] buffer = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">8192</span>];  <span class="comment">// 8KB 缓冲区</span></span><br><span class="line">            <span class="type">int</span> bytesRead;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 循环读取直到文件结束（read 返回 -1 表示读完）</span></span><br><span class="line">            <span class="keyword">while</span> ((bytesRead = is.read(buffer)) != -<span class="number">1</span>) &#123;</span><br><span class="line">                os.write(buffer, <span class="number">0</span>, bytesRead);  <span class="comment">// 只写入实际读取的字节数</span></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            System.out.println(<span class="string">&quot;图片复制完成！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="type">long</span> <span class="variable">end</span> <span class="operator">=</span> System.currentTimeMillis();</span><br><span class="line">        System.out.println(<span class="string">&quot;耗时：&quot;</span> + (end - start) + <span class="string">&quot;ms&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 字符流：读写文本文件 ============</span></span><br><span class="line">    <span class="comment">// 适用于纯文本文件</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">readWriteText</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">inputFile</span> <span class="operator">=</span> <span class="string">&quot;input.txt&quot;</span>;</span><br><span class="line">        <span class="type">String</span> <span class="variable">outputFile</span> <span class="operator">=</span> <span class="string">&quot;output.txt&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 基本字符流</span></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">Reader</span> <span class="variable">reader</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileReader</span>(inputFile);</span><br><span class="line">             <span class="type">Writer</span> <span class="variable">writer</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FileWriter</span>(outputFile)) &#123;</span><br><span class="line"></span><br><span class="line">            <span class="type">char</span>[] buffer = <span class="keyword">new</span> <span class="title class_">char</span>[<span class="number">1024</span>];</span><br><span class="line">            <span class="type">int</span> length;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">while</span> ((length = reader.read(buffer)) != -<span class="number">1</span>) &#123;</span><br><span class="line">                writer.write(buffer, <span class="number">0</span>, length);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            System.out.println(<span class="string">&quot;文本文件复制完成！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ BufferedReader：按行读取（推荐） ============</span></span><br><span class="line">    <span class="comment">// BufferedReader 提供了 readLine() 方法，按行读取更方便</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">readByLine</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">file</span> <span class="operator">=</span> <span class="string">&quot;log.txt&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">BufferedReader</span> <span class="variable">br</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedReader</span>(</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">FileReader</span>(file), <span class="number">8192</span>)) &#123;  <span class="comment">// 指定缓冲区大小</span></span><br><span class="line"></span><br><span class="line">            String line;</span><br><span class="line">            <span class="type">int</span> <span class="variable">lineNumber</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// readLine() 返回 null 表示文件结束</span></span><br><span class="line">            <span class="keyword">while</span> ((line = br.readLine()) != <span class="literal">null</span>) &#123;</span><br><span class="line">                lineNumber++;</span><br><span class="line">                System.out.println(lineNumber + <span class="string">&quot;: &quot;</span> + line);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ BufferedWriter：带缓冲写入 ============</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">bufferedWrite</span><span class="params">()</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">file</span> <span class="operator">=</span> <span class="string">&quot;output.txt&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">BufferedWriter</span> <span class="variable">bw</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BufferedWriter</span>(</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">FileWriter</span>(file))) &#123;</span><br><span class="line"></span><br><span class="line">            bw.write(<span class="string">&quot;第一行内容&quot;</span>);</span><br><span class="line">            bw.newLine();  <span class="comment">// 写入换行符</span></span><br><span class="line"></span><br><span class="line">            bw.write(<span class="string">&quot;第二行内容&quot;</span>);</span><br><span class="line">            bw.newLine();</span><br><span class="line"></span><br><span class="line">            bw.write(<span class="string">&quot;第三行内容&quot;</span>);</span><br><span class="line"></span><br><span class="line">            bw.flush();  <span class="comment">// 刷新缓冲区，将数据立即写入文件</span></span><br><span class="line">            System.out.println(<span class="string">&quot;写入完成！&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ Scanner：简单场景首选 ============</span></span><br><span class="line">    <span class="comment">// 适合小文件的简单读取</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">scannerRead</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">file</span> <span class="operator">=</span> <span class="string">&quot;data.txt&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(<span class="keyword">new</span> <span class="title class_">File</span>(file))) &#123;</span><br><span class="line">            scanner.useDelimiter(<span class="string">&quot;,&quot;</span>);  <span class="comment">// 指定分隔符</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">while</span> (scanner.hasNext()) &#123;</span><br><span class="line">                <span class="keyword">if</span> (scanner.hasNextInt()) &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;整数：&quot;</span> + scanner.nextInt());</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (scanner.hasNextDouble()) &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;小数：&quot;</span> + scanner.nextDouble());</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    System.out.println(<span class="string">&quot;字符串：&quot;</span> + scanner.next());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;文件不存在：&quot;</span> + e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="对象序列化"><a href="#对象序列化" class="headerlink" title="对象序列化"></a>对象序列化</h3><p><strong>序列化</strong>是将对象转换为字节序列的过程，用于将对象保存到文件或在网络上传输。<strong>反序列化</strong>是序列化的逆过程。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ============ 可序列化类 ============</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line">    <span class="comment">// serialVersionUID：版本号，序列化/反序列化时需要匹配</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> age;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// transient 修饰的字段不会被序列化</span></span><br><span class="line">    <span class="comment">// 常用于敏感信息（密码等）或不需要持久化的数据</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> String password;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Person</span><span class="params">(String name, <span class="type">int</span> age, String password)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">        <span class="built_in">this</span>.password = password;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">toString</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Person&#123;name=&#x27;&quot;</span> + name + <span class="string">&quot;&#x27;, age=&quot;</span> + age</span><br><span class="line">                + <span class="string">&quot;, password=&#x27;&quot;</span> + password + <span class="string">&quot;&#x27;&#125;&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 序列化与反序列化 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SerializationDemo</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILE</span> <span class="operator">=</span> <span class="string">&quot;person.dat&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 序列化：对象 -&gt; 文件</span></span><br><span class="line">        <span class="type">Person</span> <span class="variable">person</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Person</span>(<span class="string">&quot;张三&quot;</span>, <span class="number">25</span>, <span class="string">&quot;123456&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">ObjectOutputStream</span> <span class="variable">oos</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectOutputStream</span>(</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">FileOutputStream</span>(FILE))) &#123;</span><br><span class="line">            oos.writeObject(person);</span><br><span class="line">            System.out.println(<span class="string">&quot;序列化成功！对象：&quot;</span> + person);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 反序列化：文件 -&gt; 对象</span></span><br><span class="line">        <span class="keyword">try</span> (<span class="type">ObjectInputStream</span> <span class="variable">ois</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectInputStream</span>(</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">FileInputStream</span>(FILE))) &#123;</span><br><span class="line">            <span class="type">Person</span> <span class="variable">p</span> <span class="operator">=</span> (Person) ois.readObject();</span><br><span class="line">            System.out.println(<span class="string">&quot;反序列化成功！对象：&quot;</span> + p);</span><br><span class="line">            <span class="comment">// 注意：password 会是 null，因为被 transient 修饰</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException | ClassNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="泛型"><a href="#泛型" class="headerlink" title="泛型"></a>泛型</h2><h3 id="什么是泛型？"><a href="#什么是泛型？" class="headerlink" title="什么是泛型？"></a>什么是泛型？</h3><p><strong>泛型</strong>是 Java 5 引入的一个新特性，它的本质是<strong>参数化类型</strong>。我们可以把泛型理解成一种”类型的占位符”，在编写代码时不指定具体类型，而在使用时再确定类型。</p><p><strong>为什么需要泛型？</strong></p><p>举一个实际例子：假设我们需要一个容器来装东西。</p><p><strong>没有泛型时（使用 Object）：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用 Object 类型的容器</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ObjectBox</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Object content;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(Object content)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.content = content;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">get</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> content;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用时需要强制类型转换，容易出错</span></span><br><span class="line"><span class="type">ObjectBox</span> <span class="variable">box</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectBox</span>();</span><br><span class="line">box.set(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line"><span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> (String) box.get();  <span class="comment">// 必须强制转换</span></span><br><span class="line"></span><br><span class="line">box.set(<span class="number">123</span>);  <span class="comment">// 可以放入任何类型</span></span><br><span class="line"><span class="type">Integer</span> <span class="variable">num</span> <span class="operator">=</span> (Integer) box.get();  <span class="comment">// 如果之前放的是 String，这里会报错</span></span><br></pre></td></tr></table></figure><p><strong>有泛型时：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用泛型的容器</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GenericBox</span>&lt;T&gt; &#123;  <span class="comment">// T 是类型参数</span></span><br><span class="line">    <span class="keyword">private</span> T content;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(T content)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.content = content;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> T <span class="title function_">get</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> content;  <span class="comment">// 无需强制转换</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用时指定具体类型</span></span><br><span class="line">GenericBox&lt;String&gt; stringBox = <span class="keyword">new</span> <span class="title class_">GenericBox</span>&lt;&gt;();</span><br><span class="line">stringBox.set(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line"><span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> stringBox.get();  <span class="comment">// 无需强制转换，类型安全</span></span><br><span class="line"></span><br><span class="line">GenericBox&lt;Integer&gt; intBox = <span class="keyword">new</span> <span class="title class_">GenericBox</span>&lt;&gt;();</span><br><span class="line">intBox.set(<span class="number">123</span>);</span><br><span class="line"><span class="type">Integer</span> <span class="variable">num</span> <span class="operator">=</span> intBox.get();  <span class="comment">// 无需强制转换</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 编译阶段就会报错，无法放入错误类型</span></span><br><span class="line"><span class="comment">// stringBox.set(123);  // 编译错误！</span></span><br></pre></td></tr></table></figure><p><strong>泛型的优势：</strong></p><ol><li><strong>类型安全</strong>：编译时检查类型，防止 ClassCastException</li><li><strong>消除强制类型转换</strong>：代码更简洁</li><li><strong>代码复用</strong>：一套代码可以处理多种类型</li></ol><h3 id="泛型体系"><a href="#泛型体系" class="headerlink" title="泛型体系"></a>泛型体系</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[泛型] --> B[泛型类 类定义时使用泛型]    A --> C[泛型接口 接口定义时使用泛型]    A --> D[泛型方法 方法定义时使用泛型]    A --> E[泛型通配符 灵活的类型限定]    style A fill:#fff3e0</pre></div><h3 id="泛型类与泛型接口"><a href="#泛型类与泛型接口" class="headerlink" title="泛型类与泛型接口"></a>泛型类与泛型接口</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ============ 泛型类 ============</span></span><br><span class="line"><span class="comment">// Box&lt;T&gt; 中的 T 被称为类型参数（Type Parameter）</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Box</span>&lt;T&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> T content;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">set</span><span class="params">(T content)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.content = content;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> T <span class="title function_">get</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> content;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 多个类型参数</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Pair</span>&lt;K, V&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> K key;</span><br><span class="line">    <span class="keyword">private</span> V value;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Pair</span><span class="params">(K key, V value)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.key = key;</span><br><span class="line">        <span class="built_in">this</span>.value = value;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> K <span class="title function_">getKey</span><span class="params">()</span> &#123; <span class="keyword">return</span> key; &#125;</span><br><span class="line">    <span class="keyword">public</span> V <span class="title function_">getValue</span><span class="params">()</span> &#123; <span class="keyword">return</span> value; &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 泛型接口 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Container</span>&lt;K, V&gt; &#123;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">put</span><span class="params">(K key, V value)</span>;</span><br><span class="line">    V <span class="title function_">get</span><span class="params">(K key)</span>;</span><br><span class="line">    <span class="type">boolean</span> <span class="title function_">contains</span><span class="params">(K key)</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实现泛型接口时，可以指定具体类型</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">StringIntegerContainer</span> <span class="keyword">implements</span> <span class="title class_">Container</span>&lt;String, Integer&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, Integer&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">put</span><span class="params">(String key, Integer value)</span> &#123;</span><br><span class="line">        map.put(key, value);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">get</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> map.get(key);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">contains</span><span class="params">(String key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> map.containsKey(key);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 也可以继续使用泛型</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">GenericContainer</span>&lt;K, V&gt; <span class="keyword">implements</span> <span class="title class_">Container</span>&lt;K, V&gt; &#123;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;K, V&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">put</span><span class="params">(K key, V value)</span> &#123;</span><br><span class="line">        map.put(key, value);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> V <span class="title function_">get</span><span class="params">(K key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> map.get(key);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">contains</span><span class="params">(K key)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> map.containsKey(key);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ============ 使用示例 ============</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GenericDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 泛型类使用</span></span><br><span class="line">        Box&lt;String&gt; stringBox = <span class="keyword">new</span> <span class="title class_">Box</span>&lt;&gt;();</span><br><span class="line">        stringBox.set(<span class="string">&quot;Hello&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;Box 内容：&quot;</span> + stringBox.get());</span><br><span class="line"></span><br><span class="line">        Box&lt;Integer&gt; intBox = <span class="keyword">new</span> <span class="title class_">Box</span>&lt;&gt;();</span><br><span class="line">        intBox.set(<span class="number">123</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;Box 内容：&quot;</span> + intBox.get());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 键值对使用</span></span><br><span class="line">        Pair&lt;String, Integer&gt; pair = <span class="keyword">new</span> <span class="title class_">Pair</span>&lt;&gt;(<span class="string">&quot;语文&quot;</span>, <span class="number">90</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;键值对：&quot;</span> + pair.getKey() + <span class="string">&quot; = &quot;</span> + pair.getValue());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 泛型接口使用</span></span><br><span class="line">        Container&lt;String, Integer&gt; container = <span class="keyword">new</span> <span class="title class_">StringIntegerContainer</span>();</span><br><span class="line">        container.put(<span class="string">&quot;数学&quot;</span>, <span class="number">95</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;容器内容：&quot;</span> + container.get(<span class="string">&quot;数学&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="泛型方法"><a href="#泛型方法" class="headerlink" title="泛型方法"></a>泛型方法</h3><p>泛型方法可以在普通类中定义，不需要类本身是泛型的。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GenericMethodDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 基本泛型方法 ============</span></span><br><span class="line">    <span class="comment">// &lt;T&gt; 表示这是一个泛型方法，T 是类型参数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="keyword">void</span> <span class="title function_">printArray</span><span class="params">(T[] array)</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (T element : array) &#123;</span><br><span class="line">            System.out.print(element + <span class="string">&quot; &quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 返回类型也是泛型 ============</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; <span class="type">int</span> <span class="title function_">findIndex</span><span class="params">(T[] array, T target)</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; array.length; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (array[i].equals(target)) &#123;</span><br><span class="line">                <span class="keyword">return</span> i;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 多个类型参数 ============</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;K, V&gt; Map&lt;K, V&gt; <span class="title function_">createMap</span><span class="params">(K key, V value)</span> &#123;</span><br><span class="line">        Map&lt;K, V&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">        map.put(key, value);</span><br><span class="line">        <span class="keyword">return</span> map;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 限制类型上限 ============</span></span><br><span class="line">    <span class="comment">// &lt;T extends Number&gt; 表示 T 必须是 Number 或其子类</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;T <span class="keyword">extends</span> <span class="title class_">Number</span>&gt; <span class="type">double</span> <span class="title function_">sum</span><span class="params">(T a, T b)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> a.doubleValue() + b.doubleValue();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ 比较器示例 ============</span></span><br><span class="line">    <span class="comment">// &lt;T extends Comparable&lt;T&gt;&gt; 确保 T 可以比较</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> &lt;T <span class="keyword">extends</span> <span class="title class_">Comparable</span>&lt;T&gt;&gt; T <span class="title function_">findMax</span><span class="params">(T a, T b)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (a.compareTo(b) &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> a;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> b;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        Integer[] intArray = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>&#125;;</span><br><span class="line">        String[] strArray = &#123;<span class="string">&quot;A&quot;</span>, <span class="string">&quot;B&quot;</span>, <span class="string">&quot;C&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 泛型方法调用</span></span><br><span class="line">        printArray(intArray);  <span class="comment">// 输出：1 2 3 4 5</span></span><br><span class="line">        printArray(strArray);  <span class="comment">// 输出：A B C</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 查找索引</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> findIndex(intArray, <span class="number">3</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;3 在数组中的索引：&quot;</span> + index);  <span class="comment">// 2</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 创建 Map</span></span><br><span class="line">        Map&lt;String, Integer&gt; map = createMap(<span class="string">&quot;年龄&quot;</span>, <span class="number">25</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;Map：&quot;</span> + map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 类型限制</span></span><br><span class="line">        System.out.println(<span class="string">&quot;求和：&quot;</span> + sum(<span class="number">1</span>, <span class="number">2.5</span>));  <span class="comment">// 3.5</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 最大值</span></span><br><span class="line">        System.out.println(<span class="string">&quot;最大值：&quot;</span> + findMax(<span class="number">10</span>, <span class="number">20</span>));  <span class="comment">// 20</span></span><br><span class="line">        System.out.println(<span class="string">&quot;最大值：&quot;</span> + findMax(<span class="string">&quot;apple&quot;</span>, <span class="string">&quot;banana&quot;</span>));  <span class="comment">// banana</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="泛型通配符"><a href="#泛型通配符" class="headerlink" title="泛型通配符"></a>泛型通配符</h3><p>泛型通配符用于泛型方法的参数中，提供更灵活的类型处理。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WildcardDemo</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ &lt;? extends T&gt; 上限通配符 ============</span></span><br><span class="line">    <span class="comment">// 表示未知类型是 T 或 T 的子类，只能读取（作为生产者）</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">printNumbers</span><span class="params">(List&lt;? extends Number&gt; list)</span> &#123;</span><br><span class="line">        <span class="comment">// 可以读取，但类型未知</span></span><br><span class="line">        <span class="keyword">for</span> (Number num : list) &#123;</span><br><span class="line">            System.out.println(num + <span class="string">&quot; &quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 不能写入任何东西！因为不知道具体是 Integer 还是 Double</span></span><br><span class="line">        <span class="comment">// list.add(1);  // 编译错误！</span></span><br><span class="line">        <span class="comment">// list.add(1.0); // 编译错误！</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ &lt;? super T&gt; 下限通配符 ============</span></span><br><span class="line">    <span class="comment">// 表示未知类型是 T 或 T 的父类，只能写入（作为消费者）</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">addNumbers</span><span class="params">(List&lt;? <span class="built_in">super</span> Integer&gt; list)</span> &#123;</span><br><span class="line">        <span class="comment">// 可以写入 Integer 或其子类</span></span><br><span class="line">        list.add(<span class="number">1</span>);</span><br><span class="line">        list.add(<span class="number">2</span>);</span><br><span class="line">        list.add(Integer.valueOf(<span class="number">3</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 读取时只能当 Object 处理</span></span><br><span class="line">        <span class="comment">// Number num = list.get(0);  // 编译错误！</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> list.get(<span class="number">0</span>);  <span class="comment">// 只能当 Object 处理</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// ============ &lt;?&gt; 无界通配符 ============</span></span><br><span class="line">    <span class="comment">// 表示未知类型，可以读写，但类型不安全需要自己注意</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">printAnyList</span><span class="params">(List&lt;?&gt; list)</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (Object obj : list) &#123;</span><br><span class="line">            System.out.println(obj);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 可以写入 null</span></span><br><span class="line">        <span class="comment">// list.add(&quot;string&quot;);  // 编译错误！</span></span><br><span class="line">        list.add(<span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 读取时只能当 Object 处理</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">element</span> <span class="operator">=</span> list.get(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 准备测试数据</span></span><br><span class="line">        List&lt;Integer&gt; intList = Arrays.asList(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);</span><br><span class="line">        List&lt;Double&gt; doubleList = Arrays.asList(<span class="number">1.1</span>, <span class="number">2.2</span>, <span class="number">3.3</span>);</span><br><span class="line">        List&lt;Number&gt; numberList = Arrays.asList(<span class="number">1</span>, <span class="number">2.0</span>, <span class="number">3L</span>);</span><br><span class="line">        List&lt;Object&gt; objectList = Arrays.asList(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &lt;? extends Number&gt; 可以接受 Integer、Double、Number</span></span><br><span class="line">        System.out.println(<span class="string">&quot;=== printNumbers ===&quot;</span>);</span><br><span class="line">        printNumbers(intList);</span><br><span class="line">        printNumbers(doubleList);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &lt;? super Integer&gt; 可以接受 Integer、Number、Object</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== addNumbers ===&quot;</span>);</span><br><span class="line">        addNumbers(intList);</span><br><span class="line">        addNumbers(numberList);</span><br><span class="line">        System.out.println(<span class="string">&quot;添加后的 Integer 列表：&quot;</span> + intList);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// &lt;?&gt; 可以接受任何类型</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== printAnyList ===&quot;</span>);</span><br><span class="line">        printAnyList(intList);</span><br><span class="line">        printAnyList(objectList);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>通配符记忆口诀：</strong></p><ul><li><strong><code>&lt;? extends T&gt;</code></strong> — “我是 T 的消费者，只能读，不能写”（Producer Extends）</li><li><strong><code>&lt;? super T&gt;</code></strong> — “我是 T 的生产者，只能写，不能读”（Consumer Super）</li></ul><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[泛型通配符] --> B[extends T 上限 只读]    A --> C[super T 下限 只写]    A --> D[无界 ? 读写 Object]    style A fill:#fff3e0</pre></div><hr><h2 id="反射机制"><a href="#反射机制" class="headerlink" title="反射机制"></a>反射机制</h2><h3 id="什么是反射？"><a href="#什么是反射？" class="headerlink" title="什么是反射？"></a>什么是反射？</h3><p><strong>反射（Reflection）</strong> 是 Java 的一个强大特性，它允许程序在<strong>运行时</strong>动态地获取类的信息、创建对象、调用方法和访问属性。</p><p>正常情况下，我们在编译时就知道要使用哪个类：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(<span class="string">&quot;hello&quot;</span>);  <span class="comment">// 编译时就知道是 String</span></span><br><span class="line">str.substring(<span class="number">0</span>, <span class="number">2</span>);               <span class="comment">// 编译时就知道有 substring 方法</span></span><br></pre></td></tr></table></figure><p>但有些场景下，<strong>我们在编译时不知道要操作哪个类</strong>，比如：</p><ul><li>开发框架（Spring、Hibernate）需要在运行时加载类</li><li>注解处理器需要在运行时读取注解信息</li><li>动态代理、RPC 框架等</li></ul><p><strong>反射就是在程序运行时自我探索和操作的能力。</strong></p><h3 id="反射核心-API"><a href="#反射核心-API" class="headerlink" title="反射核心 API"></a>反射核心 API</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>flowchart LR    A[反射 API] --> B[Class 类本身]    A --> C[Field 属性]    A --> D[Method 方法]    A --> E[Constructor 构造方法]    B --> B1[getName]    B --> B2[newInstance]    B --> B3[getDeclaredFields]    C --> C1[get]    C --> C2[set]    C --> C3[setAccessible]    D --> D1[invoke]    D --> D2[getParameterTypes]    style A fill:#fff3e0</pre></div><h3 id="获取-Class-对象"><a href="#获取-Class-对象" class="headerlink" title="获取 Class 对象"></a>获取 Class 对象</h3><p>Class 对象是反射的入口，每个类在 JVM 中都只有一个 Class 对象。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReflectDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;Hello&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式一：使用 getClass() 方法</span></span><br><span class="line">        <span class="comment">// 任何对象都有 getClass() 方法</span></span><br><span class="line">        Class&lt;?&gt; c1 = str.getClass();</span><br><span class="line">        System.out.println(<span class="string">&quot;方式一获取：&quot;</span> + c1.getName());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式二：使用 Class.forName()</span></span><br><span class="line">        <span class="comment">// 最常用，可以动态指定类名</span></span><br><span class="line">        Class&lt;?&gt; c2 = Class.forName(<span class="string">&quot;java.lang.String&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;方式二获取：&quot;</span> + c2.getName());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式三：使用 .class 属性</span></span><br><span class="line">        <span class="comment">// 最简单直接，适用于已知类型的情况</span></span><br><span class="line">        Class&lt;?&gt; c3 = String.class;</span><br><span class="line">        System.out.println(<span class="string">&quot;方式三获取：&quot;</span> + c3.getName());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式四：基本类型的 TYPE</span></span><br><span class="line">        <span class="comment">// 每个基本类型都有一个包装类，包装类有 TYPE 属性</span></span><br><span class="line">        Class&lt;?&gt; c4 = Integer.TYPE;</span><br><span class="line">        System.out.println(<span class="string">&quot;Integer.TYPE：&quot;</span> + c4);  <span class="comment">// int</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 验证：同一个类的 Class 对象是同一个</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 验证 Class 唯一性 ===&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;c1 == c2：&quot;</span> + (c1 == c2));  <span class="comment">// true</span></span><br><span class="line">        System.out.println(<span class="string">&quot;c2 == c3：&quot;</span> + (c2 == c3));  <span class="comment">// true</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="操作类的结构"><a href="#操作类的结构" class="headerlink" title="操作类的结构"></a>操作类的结构</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 示例类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String name;</span><br><span class="line">    <span class="keyword">protected</span> <span class="type">int</span> age;</span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Person</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">Person</span><span class="params">(String name, <span class="type">int</span> age)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sayHello</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;你好，我是&quot;</span> + name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">privateMethod</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;这是私有方法&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReflectStructure</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        Class&lt;?&gt; clazz = Person.class;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 获取类信息 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;=== 类信息 ===&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;完整类名：&quot;</span> + clazz.getName());        <span class="comment">// 包名.类名</span></span><br><span class="line">        System.out.println(<span class="string">&quot;简单类名：&quot;</span> + clazz.getSimpleName());   <span class="comment">// 只有类名</span></span><br><span class="line">        System.out.println(<span class="string">&quot;包名：&quot;</span> + clazz.getPackage());          <span class="comment">// 所在包</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 获取属性 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 属性信息 ===&quot;</span>);</span><br><span class="line">        <span class="comment">// getDeclaredFields() 获取所有声明的属性（包括私有）</span></span><br><span class="line">        <span class="keyword">for</span> (Field field : clazz.getDeclaredFields()) &#123;</span><br><span class="line">            <span class="comment">// 获取修饰符（public、private 等）</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">modifier</span> <span class="operator">=</span> Modifier.toString(field.getModifiers());</span><br><span class="line">            <span class="comment">// 获取类型名</span></span><br><span class="line">            <span class="type">String</span> <span class="variable">typeName</span> <span class="operator">=</span> field.getType().getSimpleName();</span><br><span class="line">            System.out.println(modifier + <span class="string">&quot; &quot;</span> + typeName + <span class="string">&quot; &quot;</span> + field.getName());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 输出：</span></span><br><span class="line">        <span class="comment">// public String name</span></span><br><span class="line">        <span class="comment">// protected int age</span></span><br><span class="line">        <span class="comment">// private String password</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 获取方法 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 方法信息 ===&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Method method : clazz.getDeclaredMethods()) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">modifier</span> <span class="operator">=</span> Modifier.toString(method.getModifiers());</span><br><span class="line">            <span class="type">String</span> <span class="variable">returnType</span> <span class="operator">=</span> method.getReturnType().getSimpleName();</span><br><span class="line">            <span class="type">String</span> <span class="variable">methodName</span> <span class="operator">=</span> method.getName();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 获取参数类型</span></span><br><span class="line">            Class&lt;?&gt;[] paramTypes = method.getParameterTypes();</span><br><span class="line">            <span class="type">String</span> <span class="variable">params</span> <span class="operator">=</span> Arrays.stream(paramTypes)</span><br><span class="line">                    .map(Class::getSimpleName)</span><br><span class="line">                    .collect(Collectors.joining(<span class="string">&quot;, &quot;</span>));</span><br><span class="line"></span><br><span class="line">            System.out.println(modifier + <span class="string">&quot; &quot;</span> + returnType + <span class="string">&quot; &quot;</span></span><br><span class="line">                    + methodName + <span class="string">&quot;(&quot;</span> + params + <span class="string">&quot;)&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 获取构造方法 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 构造方法 ===&quot;</span>);</span><br><span class="line">        <span class="keyword">for</span> (Constructor&lt;?&gt; constructor : clazz.getDeclaredConstructors()) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">modifier</span> <span class="operator">=</span> Modifier.toString(constructor.getModifiers());</span><br><span class="line">            <span class="type">String</span> <span class="variable">constructorName</span> <span class="operator">=</span> constructor.getName();</span><br><span class="line"></span><br><span class="line">            Class&lt;?&gt;[] paramTypes = constructor.getParameterTypes();</span><br><span class="line">            <span class="type">String</span> <span class="variable">params</span> <span class="operator">=</span> Arrays.stream(paramTypes)</span><br><span class="line">                    .map(Class::getSimpleName)</span><br><span class="line">                    .collect(Collectors.joining(<span class="string">&quot;, &quot;</span>));</span><br><span class="line"></span><br><span class="line">            System.out.println(modifier + <span class="string">&quot; &quot;</span> + constructorName + <span class="string">&quot;(&quot;</span> + params + <span class="string">&quot;)&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="反射创建对象与调用方法"><a href="#反射创建对象与调用方法" class="headerlink" title="反射创建对象与调用方法"></a>反射创建对象与调用方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReflectInvoke</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        Class&lt;?&gt; clazz = Person.class;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 创建对象 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;=== 创建对象 ===&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式一：使用无参构造创建对象</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">obj1</span> <span class="operator">=</span> clazz.getDeclaredConstructor().newInstance();</span><br><span class="line">        System.out.println(<span class="string">&quot;无参构造创建：&quot;</span> + obj1);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 方式二：使用有参构造创建对象</span></span><br><span class="line">        Constructor&lt;?&gt; constructor = clazz.getConstructor(String.class, <span class="type">int</span>.class);</span><br><span class="line">        <span class="type">Object</span> <span class="variable">obj2</span> <span class="operator">=</span> constructor.newInstance(<span class="string">&quot;张三&quot;</span>, <span class="number">25</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;有参构造创建：&quot;</span> + obj2);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 操作属性 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 操作属性 ===&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 操作公共属性</span></span><br><span class="line">        <span class="type">Field</span> <span class="variable">nameField</span> <span class="operator">=</span> clazz.getField(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">        nameField.set(obj2, <span class="string">&quot;李四&quot;</span>);  <span class="comment">// 设置属性值</span></span><br><span class="line">        System.out.println(<span class="string">&quot;修改后的 name：&quot;</span> + nameField.get(obj2));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 操作私有属性</span></span><br><span class="line">        <span class="type">Field</span> <span class="variable">passwordField</span> <span class="operator">=</span> clazz.getDeclaredField(<span class="string">&quot;password&quot;</span>);</span><br><span class="line">        passwordField.setAccessible(<span class="literal">true</span>);  <span class="comment">// 必须设置可访问，否则会抛异常</span></span><br><span class="line">        passwordField.set(obj2, <span class="string">&quot;newPassword&quot;</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;私有 password：&quot;</span> + passwordField.get(obj2));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 调用方法 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 调用方法 ===&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用公共方法</span></span><br><span class="line">        <span class="type">Method</span> <span class="variable">sayHello</span> <span class="operator">=</span> clazz.getMethod(<span class="string">&quot;sayHello&quot;</span>);</span><br><span class="line">        sayHello.invoke(obj2);  <span class="comment">// 输出：你好，我是李四</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用重载方法：需要指定参数类型</span></span><br><span class="line">        <span class="comment">// 假设 Person 有一个 sayHello(String greeting) 方法</span></span><br><span class="line">        <span class="comment">// Method greetMethod = clazz.getMethod(&quot;sayHello&quot;, String.class);</span></span><br><span class="line">        <span class="comment">// greetMethod.invoke(obj2, &quot;早上好&quot;);  // 输出：早上好，我是李四</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 调用私有方法</span></span><br><span class="line">        <span class="type">Method</span> <span class="variable">privateMethod</span> <span class="operator">=</span> clazz.getDeclaredMethod(<span class="string">&quot;privateMethod&quot;</span>);</span><br><span class="line">        privateMethod.setAccessible(<span class="literal">true</span>);  <span class="comment">// 设置可访问</span></span><br><span class="line">        privateMethod.invoke(obj2);  <span class="comment">// 输出：这是私有方法</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// ============ 动态调用示例 ============</span></span><br><span class="line">        System.out.println(<span class="string">&quot;\n=== 动态调用 ===&quot;</span>);</span><br><span class="line">        <span class="comment">// 假设我们要根据配置调用不同的方法</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">methodName</span> <span class="operator">=</span> <span class="string">&quot;sayHello&quot;</span>;</span><br><span class="line">        <span class="type">Method</span> <span class="variable">dynamicMethod</span> <span class="operator">=</span> clazz.getMethod(methodName);</span><br><span class="line">        dynamicMethod.invoke(obj2);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="反射优缺点"><a href="#反射优缺点" class="headerlink" title="反射优缺点"></a>反射优缺点</h3><table><thead><tr><th>方面</th><th>说明</th></tr></thead><tbody><tr><td><strong>优点</strong></td><td>动态加载类、框架基石（Spring&#x2F;Hibernate）、运行时操作、极大灵活性</td></tr><tr><td><strong>缺点</strong></td><td>性能开销大（比直接调用慢数十倍）、破坏封装性、存在安全风险</td></tr><tr><td><strong>使用建议</strong></td><td>日常业务代码少用，框架和工具类中常用</td></tr></tbody></table><h3 id="反射的实际应用场景"><a href="#反射的实际应用场景" class="headerlink" title="反射的实际应用场景"></a>反射的实际应用场景</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 场景一：Spring 依赖注入</span></span><br><span class="line"><span class="comment">// Spring 容器在启动时通过反射创建 Bean 并注入属性</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 场景二：JSON 序列化（Fastjson、Gson）</span></span><br><span class="line"><span class="comment">// 通过反射读取对象的属性，将它们转换为 JSON</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 场景三：注解处理器</span></span><br><span class="line"><span class="comment">// 通过反射读取类、方法、属性上的注解，做相应处理</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 场景四：通用对象克隆</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T&gt; T <span class="title function_">deepClone</span><span class="params">(T obj)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">    <span class="type">ByteArrayOutputStream</span> <span class="variable">bos</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>();</span><br><span class="line">    <span class="type">ObjectOutputStream</span> <span class="variable">oos</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectOutputStream</span>(bos);</span><br><span class="line">    oos.writeObject(obj);</span><br><span class="line"></span><br><span class="line">    <span class="type">ByteArrayInputStream</span> <span class="variable">bis</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(bos.toByteArray());</span><br><span class="line">    <span class="type">ObjectInputStream</span> <span class="variable">ois</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectInputStream</span>(bis);</span><br><span class="line">    <span class="meta">@SuppressWarnings(&quot;unchecked&quot;)</span></span><br><span class="line">    <span class="type">T</span> <span class="variable">clone</span> <span class="operator">=</span> (T) ois.readObject();</span><br><span class="line">    <span class="keyword">return</span> clone;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="📌-总结"><a href="#📌-总结" class="headerlink" title="📌 总结"></a>📌 总结</h2><p>本文系统地总结了 Java 基础的核心知识点：</p><h3 id="知识框架图"><a href="#知识框架图" class="headerlink" title="知识框架图"></a>知识框架图</h3><div class="mermaid-wrap"><pre class="mermaid-src" data-config="{}" hidden>mindmap  root((Java 基础))    Java 程序运行流程      JavaC 编译      ClassLoader 加载      JVM 执行      字节码跨平台    数据类型      基本类型 8 种      引用类型      类型转换    面向对象      封装      继承      多态    集合框架      List      Set      Map    多线程      线程创建      线程同步      生产者消费者    I/O 流      字节流      字符流      对象序列化    泛型      泛型类      泛型方法      通配符    反射      获取 Class      操作属性      调用方法</pre></div><h3 id="核心要点回顾"><a href="#核心要点回顾" class="headerlink" title="核心要点回顾"></a>核心要点回顾</h3><table><thead><tr><th>知识点</th><th>核心概念</th><th>关键点</th></tr></thead><tbody><tr><td><strong>数据类型</strong></td><td>基本类型 vs 引用类型</td><td>自动转型、强制转型、精度丢失</td></tr><tr><td><strong>面向对象</strong></td><td>封装、继承、多态</td><td>private&#x2F;protected&#x2F;public、extends、override&#x2F;overload</td></tr><tr><td><strong>集合框架</strong></td><td>List&#x2F;Set&#x2F;Map</td><td>ArrayList&#x2F;HashSet&#x2F;HashMap 最常用</td></tr><tr><td><strong>多线程</strong></td><td>生命周期、同步机制</td><td>synchronized、wait&#x2F;notify、线程安全</td></tr><tr><td><strong>I&#x2F;O 流</strong></td><td>字节流、字符流、对象流</td><td>try-with-resources、自动关闭</td></tr><tr><td><strong>泛型</strong></td><td>类型参数化、安全检查</td><td>&lt;? extends T&gt;、&lt;? super T&gt;</td></tr><tr><td><strong>反射</strong></td><td>运行时动态操作</td><td>Class.forName、Method.invoke</td></tr></tbody></table><blockquote><p>纸上得来终觉浅，绝知此事要躬行 🚀</p><p>学习 Java 最好的方式就是多敲代码，遇到问题多思考。阅读源码（如 JDK 源码、Spring 源码）是提升内功的有效途径。</p></blockquote><hr><p><em>📅 本文首次发布于 2026 年 5 月 20 日</em></p>]]>
    </content>
    <id>https://blog.codenav.top/java-basics/</id>
    <link href="https://blog.codenav.top/java-basics/"/>
    <published>2026-05-20T01:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="Java-基础核心总结-📚"><a href="#Java-基础核心总结-📚" class="headerlink" title="Java 基础核心总结 📚"></a>Java 基础核心总结 📚</h1><blockquote>
<p>Java 是一门面]]>
    </summary>
    <title>Java 基础核心总结</title>
    <updated>2026-05-20T04:21:07.805Z</updated>
  </entry>
</feed>
