<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://www.cyberpioneer.club/</id>
  <title type="text">Cyber先锋社</title>
  <subtitle type="text">探索信息技术的先锋阵地</subtitle>
  <updated>2026-10-29T00:00:00.000Z</updated>
  <author><name>Cyber先锋社</name></author>
  <link rel="alternate" href="https://www.cyberpioneer.club/"/>
  <link rel="self" href="https://www.cyberpioneer.club/atom.xml"/>
  <generator uri="https://github.com/CuteLeaf/Firefly">Firefly v6.16.8</generator>
    <entry>
      <id>https://www.cyberpioneer.club/posts/hello-cyber-pioneer/</id>
      <title type="text">Cyber先锋社官方博客正式上线！</title>
      <published>2026-10-28T00:00:00.000Z</published>
      <updated>2026-10-28T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/hello-cyber-pioneer/"/>
      <summary type="text">Cyber先锋社官方博客今天正式创建上线！今后社团动态、活动通知与技术文章都会第一时间在这里发布，欢迎收藏我们的新阵地。</summary>
      <content type="html"><![CDATA[<section><h2>🎉 博客上线了<a href="#-博客上线了"><span>#</span></a></h2><p>经过一段时间的筹备，<strong>Cyber先锋社（Cyber Pioneer Club）</strong> 的官方博客今天正式创建并与大家见面！</p><p>Cyber先锋社是一支专注于<strong>网络安全与信息技术</strong>的学生技术社团。此前我们的动态散落在群通知和公众号里，从今天起，这个博客将成为社团的官方阵地——<strong>社团动态、活动通知、技术文章都会第一时间在这里发布</strong>，欢迎收藏我们的地址。</p></section>
<section><h2>🛡️ 在这里你能看到什么<a href="#️-在这里你能看到什么"><span>#</span></a></h2><p>结合社团一直以来的活动方向，博客初期将围绕以下栏目更新：</p><ul>
<li><strong>社团动态</strong>：活动预告、赛事战报、纳新通知</li>
<li><strong>技术分享</strong>：CTF 训练营复盘、Web/逆向/密码学方向的入门与进阶文章</li>
<li><strong>活动记录</strong>：每周分享会与靶场演练的总结存档</li>
<li><strong>开源项目</strong>：社团共创工具的开发日志</li>
</ul></section>
<section><h2>📣 想加入社团？<a href="#-想加入社团"><span>#</span></a></h2><p>如果你对网络安全、黑客技术充满好奇，想找到一群志同道合的技术伙伴——欢迎加入 Cyber先锋社！零基础也没关系，热情和坚持最重要。可以通过 <a href="/about/">关于页面</a> 上的联系方式找到我们。</p></section>
<section><h2>🚀 关于本站<a href="#-关于本站"><span>#</span></a></h2><p>本站基于 <a href="https://astro.build" target="_blank">Astro</a> + <a href="https://github.com/CuteLeaf/Firefly" target="_blank">Firefly</a> 主题构建，源码托管在 <a href="https://github.com/1376524890/cyberpioneer_blog" target="_blank">GitHub</a>，欢迎 Star 与共建。</p><hr /><p><em>这是本站的第一篇文章。博客刚起步，内容会逐步丰富，未来无限可能。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-01/</id>
      <title type="text">C++ 入门教程（一）：开发环境与第一个程序</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-01/"/>
      <summary type="text">走进 C++ 的世界：认识编译型语言、搭建开发环境、理解 main 函数与编译流程、掌握变量与输入输出流。性能之王的起点从这里开始。</summary>
      <content type="html"><![CDATA[<section><h2>为什么值得学 C++<a href="#为什么值得学-c"><span>#</span></a></h2><p>C++ 是一门”越学越值钱”的语言：操作系统、游戏引擎、数据库、高性能计算、嵌入式设备的底层几乎都由 C++ 驱动。它直接操作内存、贴近硬件，运行效率极高；同时现代 C++（11/17/20 标准）也提供了大量便利特性。</p><p>学 C++ 的过程能让你真正理解<strong>计算机是怎么工作的</strong>——这也是为什么很多高校把 C++ 作为第一门语言。相比 Python，它更严格，但也更锻炼基本功。</p></section>
<section><h2>编译型语言 vs 解释型语言<a href="#编译型语言-vs-解释型语言"><span>#</span></a></h2><p>开始前先建立一个关键概念：</p>

<table><thead><tr><th></th><th>Python</th><th>C++</th></tr></thead><tbody><tr><td>执行方式</td><td>解释器逐行执行</td><td><strong>先编译成机器码，再运行</strong></td></tr><tr><td>源文件</td><td><code>.py</code></td><td><code>.cpp</code> / <code>.cc</code></td></tr><tr><td>类型检查</td><td>运行时</td><td><strong>编译时（更严格）</strong></td></tr><tr><td>运行速度</td><td>较慢</td><td>极快</td></tr></tbody></table><p>写好的 C++ 代码不能直接运行，要经过 <strong>预处理 → 编译 → 汇编 → 链接</strong> 四步生成可执行文件。入门阶段不需要深究细节，只需知道：<strong>编辑器写代码，编译器造程序</strong>。</p></section>
<section><h2>搭建开发环境<a href="#搭建开发环境"><span>#</span></a></h2><section><h3>Windows：安装 MinGW-w64（VS Code + g++）<a href="#windows安装-mingw-w64vs-code--g"><span>#</span></a></h3><ol>
<li>下载 <a href="https://www.msys2.org/" target="_blank">MSYS2</a> 并安装</li>
<li>在 MSYS2 终端执行：</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pacman</span><span> </span><span>-S</span><span> </span><span>mingw-w64-ucrt-x86_64-gcc</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>把 <code>C:\msys64\ucrt64\bin</code> 加入系统 PATH</li>
<li>验证：</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>g++</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>推荐搭配 VS Code + C/C++ 扩展使用。也可以直接安装 Visual Studio Community（一体化但体积大）。</p></section><section><h3>macOS<a href="#macos"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>xcode-select</span><span> </span><span>--install</span><span>   </span><span># 安装命令行工具（含 clang++）</span></div></div><div><div><div>2</div></div><div><span>clang++</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Linux（Ubuntu/Debian）<a href="#linuxubuntudebian"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span><span> &amp;&amp; </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>build-essential</span></div></div><div><div><div>2</div></div><div><span>g++</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>第一个程序<a href="#第一个程序"><span>#</span></a></h2><p>新建 <code>hello.cpp</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span><span>   </span><span>// 引入输入输出库</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span><span>          // main 函数：程序的入口</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Hello, Cyber先锋社!"</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>endl</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span><span>         // 返回 0 表示程序正常结束</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译并运行：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>g++</span><span> </span><span>hello.cpp</span><span> </span><span>-o</span><span> </span><span>hello</span><span>   </span><span># 编译，-o 指定输出文件名</span></div></div><div><div><div>2</div></div><div><span>./hello</span><span>                   </span><span># 运行</span></div></div><div><div><div>3</div></div><div><span>Hello,</span><span> </span><span>Cyber先锋社!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>逐行解读</strong>：</p><ul>
<li><code>#include &lt;iostream&gt;</code>：预处理指令，引入标准输入输出流库</li>
<li><code>int main()</code>：每个 C++ 程序都从 main 函数开始执行，<code>int</code> 表示它返回一个整数</li>
<li><code>std::cout</code>：标准输出流对象，<code>&lt;&lt;</code> 把内容”流向”屏幕</li>
<li><code>std::endl</code>：换行符（并刷新缓冲区）</li>
<li><code>return 0</code>：向操作系统报告程序成功执行</li>
</ul></section>
<section><h2>变量与数据类型<a href="#变量与数据类型"><span>#</span></a></h2><p>C++ 是<strong>静态类型语言</strong>，变量必须先声明类型：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>18</span><span>;</span><span>                  // 整数（通常 4 字节）</span></div></div><div><div><div>6</div></div><div><span>    </span><span>double</span><span> </span><span>height</span><span> </span><span>=</span><span> </span><span>1.75</span><span>;</span><span>          // 双精度浮点数（8 字节）</span></div></div><div><div><div>7</div></div><div><span>    </span><span>char</span><span> </span><span>grade</span><span> </span><span>=</span><span> </span><span>'A'</span><span>;</span><span>              // 单个字符，用单引号</span></div></div><div><div><div>8</div></div><div><span>    </span><span>bool</span><span> </span><span>is_member</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span><span>         // 布尔值</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>"小明"</span><span>;</span><span>     // 字符串（需 #include &lt;string&gt;）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"姓名: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>name</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>endl</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"年龄: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>age</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>endl</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"身高: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>height</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>endl</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><section><h3>常用类型速览<a href="#常用类型速览"><span>#</span></a></h3>

<table><thead><tr><th>类型</th><th>字节</th><th>范围/说明</th></tr></thead><tbody><tr><td><code>int</code></td><td>4</td><td>约 ±21 亿</td></tr><tr><td><code>long long</code></td><td>8</td><td>约 ±9.2×10¹⁸</td></tr><tr><td><code>double</code></td><td>8</td><td>15~16 位有效数字</td></tr><tr><td><code>char</code></td><td>1</td><td>单字符</td></tr><tr><td><code>bool</code></td><td>1</td><td>true / false</td></tr><tr><td><code>std::string</code></td><td>动态</td><td>任意长度文本</td></tr></tbody></table><div><div><div></div><div>Tip</div></div><div><p>用 <code>sizeof(类型)</code> 可以查看字节数，如 <code>std::cout &lt;&lt; sizeof(int)</code>。理解内存大小是 C++ 的基本功。</p></div></div></section></section>
<section><h2>输入与输出<a href="#输入与输出"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>age</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入你的姓名: "</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>name</span><span>;</span><span>          // 从键盘读取</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入你的年龄: "</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>age</span><span>;</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 明年 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>age</span><span> </span><span>+</span><span> </span><span>1</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 岁"</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>endl</span><span>;</span></div></div><div><div><div>15</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>std::cin</code> 与 <code>std::cout</code> 方向相反：<code>&gt;&gt;</code> 把输入”流入”变量。</p><section><h3>用 using 简化书写<a href="#用-using-简化书写"><span>#</span></a></h3><p>每次写 <code>std::</code> 很啰嗦，可以在文件开头声明：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>using</span><span> </span><span>namespace</span><span><span> </span><span>std</span><span>;</span></span><span>    // 之后直接写 cout / cin / endl</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"简洁多了!"</span><span> </span><span>&lt;&lt;</span><span> </span><span>endl</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Note</div></div><div><p><code>using namespace std</code> 在大型工程中可能引发命名冲突，教学代码中用没问题，工程实践中建议保留 <code>std::</code> 前缀或局部使用。</p></div></div></section></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>编写程序输出你选的课表（每行一门课），体会 <code>endl</code> 与 <code>\n</code> 的用法</li>
<li>定义变量保存圆的半径，计算并输出周长与面积（<code>3.14159 * r * r</code>）</li>
<li>用 <code>cin</code> 读入两个整数，输出它们的和、差、积</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>C++ 是编译型语言：<code>g++ 源文件 -o 可执行文件</code> → <code>./可执行文件</code></li>
<li>程序入口是 <code>main</code> 函数，<code>return 0</code> 表示正常结束</li>
<li>变量必须声明类型，<code>int</code> / <code>double</code> / <code>char</code> / <code>bool</code> / <code>std::string</code> 是五大基础类型</li>
<li><code>std::cout &lt;&lt;</code> 输出、<code>std::cin &gt;&gt;</code> 输入，<code>using namespace std</code> 可简化书写</li>
</ul><p><strong>下一篇</strong>：分支与循环 + <code>vector</code> 容器入门——写出真正有逻辑的程序。</p><hr /><p><em>本系列为 Cyber先锋社原创教程，参考业界通用知识体系编写。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-02/</id>
      <title type="text">C++ 入门教程（二）：语法基础与运算符详解</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-02/"/>
      <summary type="text">详解 C++ 注释规范、七类运算符（算术/关系/逻辑/位/赋值/杂项）、类型转换规则（隐式/显式/constexpr）、auto 与 typedef、常量定义，配可运行示例与典型陷阱。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>上一篇搭好了环境、跑通了第一个程序。本篇把 C++ 的<strong>语法地基</strong>打牢：注释、变量细节、全部运算符与类型转换。C++ 是强类型语言，这些规则比 Python 严格得多，理解它们能少走很多弯路。</p></section>
<section><h2>一、注释与代码风格<a href="#一注释与代码风格"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 单行注释：解释"为什么"而不是"是什么"</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>/*</span></div></div><div><div><div>4</div></div><div><span><span>   </span></span><span>多行注释</span></div></div><div><div><div>5</div></div><div><span><span>   </span></span><span>常用于文件头说明、暂时禁用大段代码</span></div></div><div><div><div>6</div></div><div><span>*/</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>/**</span></div></div><div><div><div>9</div></div><div><span><span> </span></span><span>* 文档注释（Doxygen 风格）</span></div></div><div><div><div>10</div></div><div><span><span> </span></span><span>* </span><span>@brief</span><span> 计算两数之和</span></div></div><div><div><div>11</div></div><div><span><span> </span></span><span>* </span><span>@param</span><span> </span><span>a</span><span> 加数</span></div></div><div><div><div>12</div></div><div><span><span> </span></span><span>* </span><span>@param</span><span> </span><span>b</span><span> 被加数</span></div></div><div><div><div>13</div></div><div><span><span> </span></span><span>* </span><span>@return</span><span> 和</span></div></div><div><div><div>14</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>15</div></div><div><span>int</span><span> </span><span>add</span><span>(</span><span>int</span><span><span> </span><span>a</span><span>, </span></span><span>int</span><span><span> </span><span>b</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span>    </span><span>return</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>二、变量进阶<a href="#二变量进阶"><span>#</span></a></h2><section><h3>初始化的三种写法<a href="#初始化的三种写法"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span><span>       // 传统 C 风格（拷贝初始化）</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>b</span><span>(</span><span>20</span><span>);</span><span>        // 直接初始化</span></div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>c</span><span>{</span><span>30</span><span>};</span><span>        // 列表初始化（C++11，现代推荐）</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 列表初始化的杀手锏：禁止窄化转换（丢失精度直接报错）</span></div></div><div><div><div>6</div></div><div><span>int</span><span> </span><span>x</span><span>{</span><span>3.14</span><span>};</span><span>      // ❌ 编译错误！double → int 会丢失</span></div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span><span>     // ⚠ 编译器仅警告，y = 3（静默截断）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>未初始化变量的危险<a href="#未初始化变量的危险"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>n</span><span>;</span><span>            // ⚠ 值是随机的（栈上残留数据）！</span></div></div><div><div><div>2</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span>;</span><span>   // 可能输出任何数</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>m</span><span>{};</span><span>          // ✅ 值初始化为 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>军规：定义变量时永远给初值</strong>，尤其是之后要累加的计数器。</p></section><section><h3>常量<a href="#常量"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>double</span><span> </span><span>PI</span><span> </span><span>=</span><span> </span><span>3.14159</span><span>;</span><span>        // 运行时常量：定义后不可修改</span></div></div><div><div><div>2</div></div><div><span>PI</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span><span>                        // ❌ 编译错误</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 编译期常量（C++11）：值必须在编译期可计算，性能更好</span></div></div><div><div><div>5</div></div><div><span>constexpr</span><span> </span><span>int</span><span> </span><span>MAX_SIZE</span><span> </span><span>=</span><span> </span><span>100</span><span>;</span></div></div><div><div><div>6</div></div><div><span>constexpr</span><span> </span><span>double</span><span> </span><span>AREA</span><span> </span><span>=</span><span> </span><span>PI</span><span> </span><span>*</span><span> </span><span>2</span><span>;</span><span>   // ✓ 由编译期常量组合而来</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>int</span><span> </span><span>arr</span><span>[</span><span>MAX_SIZE</span><span>];</span><span>                // 数组大小需要编译期常量 ✓</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>类型别名<a href="#类型别名"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typedef</span><span> </span><span>unsigned</span><span> </span><span>long</span><span> </span><span>ulong_t</span><span>;</span><span>        // 传统写法</span></div></div><div><div><div>2</div></div><div><span>using</span><span> </span><span>score_t</span><span> </span><span>=</span><span> </span><span>double</span><span>;</span><span>               // C++11 别名声明（推荐，更清晰）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>score_t</span><span> </span><span>math</span><span> </span><span>=</span><span> </span><span>95.5</span><span>;</span></div></div><div><div><div>5</div></div><div><span>ulong_t</span><span> </span><span>big</span><span> </span><span>=</span><span> </span><span><span>100000</span><span>UL</span></span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>auto 类型推断（C++11）<a href="#auto-类型推断c11"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>auto</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>42</span><span>;</span><span>              // int</span></div></div><div><div><div>2</div></div><div><span>auto</span><span> </span><span>d</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span><span>            // double</span></div></div><div><div><div>3</div></div><div><span>auto</span><span> </span><span>s</span><span> </span><span>=</span><span> std::</span><span>string</span><span>(</span><span>"hi"</span><span>);</span><span>   // std::string</span></div></div><div><div><div>4</div></div><div><span>auto</span><span> </span><span>v</span><span> </span><span>=</span><span> std::</span><span>vector</span><span>&lt;int&gt;</span><span>{</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>};</span><span>   // 配合 STL 极大减少书写</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// auto 用于复杂类型（迭代器）是真香现场：</span></div></div><div><div><div>7</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>nums</span><span>{</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>};</span></div></div><div><div><div>8</div></div><div><span>std::vector&lt;</span><span>int</span><span>&gt;::</span><span>iterator</span><span> </span><span>it1</span><span> </span><span>=</span><span> </span><span>nums</span><span>.</span><span>begin</span><span>();</span><span>   // 啰嗦</span></div></div><div><div><div>9</div></div><div><span>auto</span><span> </span><span>it2</span><span> </span><span>=</span><span> </span><span>nums</span><span>.</span><span>begin</span><span>();</span><span>                          // 优雅</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Note</div></div><div><p><code>auto</code> 是”让编译器推断类型”，不是”动态类型”——推断完成后类型就固定了，且 auto 变量必须有初始化。</p></div></div></section></section>
<section><h2>三、运算符全解<a href="#三运算符全解"><span>#</span></a></h2><section><h3>1. 算术运算符<a href="#1-算术运算符"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 13</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>-</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 7</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>*</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 30</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>/</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 3   ⚠ 整数除法，小数被截断！</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>%</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 1   取模（两侧必须是整数）</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>10.0</span><span> </span><span>/</span><span> </span><span>3</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span> // 3.33333 有一侧是浮点就是浮点除法</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>// ⚠⚠ 整数除法是 C++ 第一大坑：</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>7</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>        // 3</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>-</span><span>7</span><span> </span><span>/</span><span> </span><span>2</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // -3（C++11 起向零取整）</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>7</span><span> </span><span>%</span><span> </span><span>-</span><span>2</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 1（商向零取整，余数符号跟被除数）</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>// 后缀/前缀 自增自减</span></div></div><div><div><div>18</div></div><div><span>    </span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span>++</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 5（先用后加）</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>++</span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 7（先加后用）</span></div></div><div><div><div>21</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>整数溢出</strong>（了解但重要）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>big</span><span> </span><span>=</span><span> </span><span>2147483647</span><span>;</span><span>    // int 最大值</span></div></div><div><div><div>2</div></div><div><span>big</span><span> </span><span>=</span><span> </span><span>big</span><span> </span><span>+</span><span> </span><span>1</span><span>;</span><span>           // 溢出！值回绕成 -2147483648（未定义行为的常见形式）</span></div></div><div><div><div>3</div></div><div><span>// 大数运算用 long long，检测用 &lt;limits&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;limits&gt;</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span><span> std::</span><span>numeric_limits</span><span>&lt;</span></span><span>int</span><span>&gt;::</span><span>max</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 关系与逻辑运算符<a href="#2-关系与逻辑运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>5</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 0    ⚠ 布尔值输出是 1/0</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>==</span><span> </span><span>b</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // 0</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>boolalpha</span><span>;</span><span>        // 切换为 true/false 输出</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&lt;</span><span> </span><span>b</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // true</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 逻辑：&amp;&amp; 且  || 或  ! 非</span></div></div><div><div><div>9</div></div><div><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>10</div></div><div><span>bool</span><span> </span><span>has_id</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>11</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>age</span><span> </span><span>&gt;=</span><span> </span><span>18</span><span> </span><span>&amp;&amp;</span><span> </span><span>has_id</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // true</span></div></div><div><div><div>12</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>!</span><span>has_id</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>                  // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>C++ 的布尔本质是 int（0 为假，非 0 为真）。经典错误：<code>if (x = 5)</code> 把比较写成赋值——条件永远为真，部分编译器加 <code>-Wall</code> 才会警告。</p></div></div><p>短路求值与 Python 一致：<code>&amp;&amp;</code> 左假右不算，<code>||</code> 左真右不算。</p></section><section><h3>3. 位运算符<a href="#3-位运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>unsigned</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span><span>0b</span><span>1010</span></span><span>;</span><span>    // 10（C++14 二进制字面量）</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&amp;</span><span> </span><span><span>0b</span><span>0110</span></span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 2   按位与</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>|</span><span> </span><span><span>0b</span><span>0101</span></span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 15  按位或</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>^</span><span> </span><span><span>0b</span><span>1111</span></span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 5   异或</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>~</span><span>a</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>           // 按位取反（含符号位）</span></div></div><div><div><div>7</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>2</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 40  左移 = ×4</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&gt;&gt;</span><span> </span><span>1</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 5   右移 = ÷2</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 实用技：</span></div></div><div><div><div>11</div></div><div><span>bool</span><span> </span><span>is_odd</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>&amp;</span><span> </span><span>1</span><span>;</span><span>             // 判奇偶</span></div></div><div><div><div>12</div></div><div><span>int</span><span> </span><span>half</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>&gt;&gt;</span><span> </span><span>1</span><span>;</span><span>               // 快速除2（现代编译器会自动优化，写 / 2 更清晰）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 赋值与逗号<a href="#4-赋值与逗号"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>x</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>x</span><span> </span><span>+=</span><span> </span><span>5</span><span>;</span><span>      // 15</span></div></div><div><div><div>3</div></div><div><span>x</span><span> </span><span>-=</span><span> </span><span>3</span><span>;</span><span>      // 12</span></div></div><div><div><div>4</div></div><div><span>x</span><span> </span><span>*=</span><span> </span><span>2</span><span>;</span><span>      // 24</span></div></div><div><div><div>5</div></div><div><span>x</span><span> </span><span>/=</span><span> </span><span>5</span><span>;</span><span>      // 4</span></div></div><div><div><div>6</div></div><div><span>x</span><span> </span><span>%=</span><span> </span><span>3</span><span>;</span><span>      // 1</span></div></div><div><div><div>7</div></div><div><span>x</span><span> </span><span>&lt;&lt;=</span><span> </span><span>2</span><span>;</span><span>     // 4（位运算也有复合赋值）</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>int</span><span> </span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>;</span></div></div><div><div><div>10</div></div><div><span>a</span><span> </span><span>=</span><span> (</span><span>b</span><span> </span><span>=</span><span> </span><span>1</span><span>, </span><span>c</span><span> </span><span>=</span><span> </span><span>2</span><span>, </span><span>b</span><span> </span><span>+</span><span> </span><span>c</span><span>);</span><span>   // 逗号表达式：依次求值取最后结果，a = 3（少用，可读性差）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>5. 三元与 sizeof<a href="#5-三元与-sizeof"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>2</div></div><div><span>std::</span><span>string</span><span> </span><span>s</span><span> </span><span>=</span><span> (</span><span>age</span><span> </span><span>&gt;=</span><span> </span><span>18</span><span>) </span><span>?</span><span> </span><span>"成年"</span><span> </span><span>:</span><span> </span><span>"未成年"</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>sizeof</span><span>(</span><span>int</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>            // 4 字节</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>sizeof</span><span>(</span><span>double</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>         // 8</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>sizeof</span><span>(</span><span>"hello"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>        // 6（含 '\0'）</span></div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>arr</span><span>[]{</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>};</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>sizeof</span><span>(</span><span>arr</span><span>) </span><span>/</span><span> </span><span>sizeof</span><span>(</span><span>arr</span><span>[</span><span>0</span><span>]);</span><span>   // 3 —— C 风格数组求长度</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、类型转换<a href="#四类型转换"><span>#</span></a></h2><section><h3>隐式转换（自动发生，注意方向）<a href="#隐式转换自动发生注意方向"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>42</span><span>;</span></div></div><div><div><div>2</div></div><div><span>double</span><span> </span><span>d</span><span> </span><span>=</span><span> </span><span>i</span><span>;</span><span>          // ✓ int → double（安全提升）</span></div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>3.99</span><span>;</span><span>          // ⚠ double → int（窄化，j = 3）</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>char</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>'A'</span><span>;</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span> </span><span>+</span><span> </span><span>1</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 66（char 提升为 int 参与运算）</span></div></div><div><div><div>7</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>char</span><span>(</span><span>c</span><span> </span><span>+</span><span> </span><span>1</span><span>);</span><span>      // 'B'</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>显式转换四种cast（重点）<a href="#显式转换四种cast重点"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>double</span><span> </span><span>pi</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// C 风格（能用但不推荐——一刀切，语义不明）</span></div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>a</span><span> </span><span>=</span><span> (</span><span>int</span><span>)</span><span>pi</span><span>;</span></div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>int</span><span>(</span><span>pi</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// C++ 四种具名 cast：</span></div></div><div><div><div>8</div></div><div><span>int</span><span> </span><span>c1</span><span> </span><span>=</span><span> </span><span><span>static_cast</span><span>&lt;int&gt;</span></span><span>(</span><span>pi</span><span>);</span><span>            // ① static_cast：常规数值转换（90%场景用它）</span></div></div><div><div><div>9</div></div><div><span>// ② dynamic_cast：继承体系安全向下转型（第十篇）</span></div></div><div><div><div>10</div></div><div><span>// ③ const_cast：去除 const（几乎不用）</span></div></div><div><div><div>11</div></div><div><span>// ④ reinterpret_cast：位模式重解释（底层操作，慎用）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>现代 C++ 建议</strong>：数值转换统一 <code>static_cast&lt;T&gt;(x)</code>，一眼看懂意图、便于搜索。</p></section><section><h3>字符串与数值互转（C++11）<a href="#字符串与数值互转c11"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> std::</span><span>stoi</span><span>(</span><span>"42"</span><span>);</span><span>            // string → int</span></div></div><div><div><div>4</div></div><div><span>double</span><span> </span><span>d</span><span> </span><span>=</span><span> std::</span><span>stod</span><span>(</span><span>"3.14"</span><span>);</span><span>       // string → double</span></div></div><div><div><div>5</div></div><div><span>long</span><span> </span><span>l</span><span> </span><span>=</span><span> std::</span><span>stol</span><span>(</span><span>"100000"</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>std::</span><span>string</span><span> </span><span>s1</span><span> </span><span>=</span><span> std::</span><span>to_string</span><span>(</span><span>42</span><span>);</span><span>        // int → string</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>string</span><span> </span><span>s2</span><span> </span><span>=</span><span> std::</span><span>to_string</span><span>(</span><span>3.14</span><span>);</span><span>      // "3.140000"</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、cin 的状态与错误输入<a href="#五cin-的状态与错误输入"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;limits&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入一个数: "</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>while</span><span> (</span><span>!</span><span>(std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>)) {</span><span>              // 输入失败（如输入字母）</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>std::</span><span>cin</span><span>.</span><span>clear</span><span>();</span><span>                    // 清除错误标志</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>std::</span><span>cin</span><span>.</span><span>ignore</span><span><span>(</span><span>std</span><span>::</span><span>numeric_limits</span><span>&lt;std::</span></span><span>streamsize</span><span>&gt;::</span><span>max</span><span>(), </span><span>'</span><span>\n</span><span>'</span><span>);</span><span>  // 丢弃坏输入</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"无效输入，请重新输入: "</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"你输入了 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这段”输入校验循环”是 C++ 命令行程序的标准配件，值得整段背下来。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>计算 BMI：输入身高(m)体重(kg)，输出 <code>体重/身高²</code>，保留 1 位小数（<code>std::fixed</code> + <code>std::setprecision(1)</code>，需 <code>&lt;iomanip&gt;</code>）</li>
<li>用位运算实现：交换两个 int 变量（不用第三个变量；提示 <code>^</code>）</li>
<li><code>7/2*2</code> 等于几？<code>7.0/2*2</code> 呢？先笔算再上机验证</li>
<li>输入秒数，换算为”X小时Y分Z秒”输出（用到 / 和 %）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>三种初始化，<code>{}</code> 值初始化最安全（禁窄化）；变量定义必给初值</li>
<li><code>const</code> 运行期常量、<code>constexpr</code> 编译期常量；<code>using</code> 别名优于 <code>typedef</code></li>
<li><code>auto</code> 让编译器推断类型，配 STL 神器</li>
<li>整数除法截断、<code>i++</code> vs <code>++i</code>、<code>=</code> 与 <code>==</code> 是三大新手坑</li>
<li>显式转换用 <code>static_cast</code>；字符串数值互转用 <code>stoi</code>/<code>to_string</code></li>
<li>cin 错误状态要 clear + ignore 才能恢复</li>
</ul><p><strong>下一篇</strong>：流程控制——分支、循环与 C++ 特有的范围 for。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。整数除法与类型转换请亲手验证每个示例。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-03/</id>
      <title type="text">C++ 入门教程（三）：流程控制</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-03/"/>
      <summary type="text">完整讲解 C++ 分支（if/switch）、三种循环（while/do-while/for）、范围 for 与 auto、break/continue、嵌套与经典算法练习（九九表/质数/图形打印/猜数字）。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>程序的三种结构：<strong>顺序、分支、循环</strong>。本篇讲全 C++ 的流程控制语法，与 Python 对比着学效率最高——逻辑相同，只是换了”语法外壳”。</p></section>
<section><h2>一、分支结构<a href="#一分支结构"><span>#</span></a></h2><section><h3>if / else if / else<a href="#if--else-if--else"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入成绩: "</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span> (</span><span>score</span><span> </span><span>&gt;=</span><span> </span><span>90</span><span>) {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"优秀</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> </span><span>if</span><span> (</span><span>score</span><span> </span><span>&gt;=</span><span> </span><span>80</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"良好</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> </span><span>if</span><span> (</span><span>score</span><span> </span><span>&gt;=</span><span> </span><span>60</span><span>) {</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"及格</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"不及格</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>与 Python 的差异：条件必须带<strong>圆括号</strong>、代码块用<strong>花括号</strong>、else if 中间有空格。</p></section><section><h3>switch：多值分发<a href="#switch多值分发"><span>#</span></a></h3><p>当条件是”一个变量等于哪些值”时，switch 比 if 链清晰：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>char</span><span> </span><span>op</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>double</span><span> </span><span>a</span><span>, </span><span>b</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入: 数 运算符 数（如 3 + 4）: "</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>a</span><span> </span><span>&gt;&gt;</span><span> </span><span>op</span><span> </span><span>&gt;&gt;</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>switch</span><span> (</span><span>op</span><span>) {</span></div></div><div><div><div>9</div></div><div><span>        </span><span>case</span><span> </span><span>'+'</span><span>:</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div><span>            </span><span>break</span><span>;</span><span>                    // ⚠ 不写 break 会"贯穿"到下一分支！</span></div></div><div><div><div>12</div></div><div><span>        </span><span>case</span><span> </span><span>'-'</span><span>:</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>-</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>14</div></div><div><span>            </span><span>break</span><span>;</span></div></div><div><div><div>15</div></div><div><span>        </span><span>case</span><span> </span><span>'*'</span><span>:</span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>*</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>17</div></div><div><span>            </span><span>break</span><span>;</span></div></div><div><div><div>18</div></div><div><span>        </span><span>case</span><span> </span><span>'/'</span><span>:</span></div></div><div><div><div>19</div></div><div><span>            </span><span>if</span><span> (</span><span>b</span><span> </span><span>!=</span><span> </span><span>0</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>/</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>20</div></div><div><span>            </span><span>else</span><span>        std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"除数不能为0</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>21</div></div><div><span>            </span><span>break</span><span>;</span></div></div><div><div><div>22</div></div><div><span>        </span><span>default</span><span>:</span><span>                      // 兜底分支</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"不支持的运算符</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>switch 的规矩</strong>：case 值必须是<strong>整数或枚举常量</strong>（不能是 double、不能是字符串）；每个分支末尾写 break，除非刻意利用贯穿。</p><div><div><div></div><div>Warning</div></div><div><p>忘 break 是 switch 第一大坑：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>x</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>switch</span><span> (</span><span>x</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>case</span><span> </span><span>1</span><span>: std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"一"</span><span>;</span><span>    // 输出"一二"——贯穿了！</span></div></div><div><div><div>4</div></div><div><span>    </span><span>case</span><span> </span><span>2</span><span>: std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"二"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></div></div></section><section><h3>三元运算符<a href="#三元运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>max_val</span><span> </span><span>=</span><span> (</span><span>a</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>) </span><span>?</span><span> </span><span>a</span><span> </span><span>:</span><span> </span><span>b</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、循环结构<a href="#二循环结构"><span>#</span></a></h2><section><h3>while：条件前置<a href="#while条件前置"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span>, </span><span>sum</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"输入 n: "</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>while</span><span> (</span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>n</span><span>) {</span></div></div><div><div><div>9</div></div><div><span>        </span><span>sum</span><span> </span><span>+=</span><span> </span><span>i</span><span>;</span></div></div><div><div><div>10</div></div><div><span>        </span><span>++</span><span>i</span><span>;</span><span>              // 别忘了推进条件</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"1~"</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 的和是 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>sum</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>do-while：先斩后奏（C++ 特有常见）<a href="#do-while先斩后奏c-特有常见"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>choice</span><span>;</span></div></div><div><div><div>2</div></div><div><span>do</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"1.开始 2.设置 0.退出</span><span>\n</span><span>请选择: "</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>choice</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>// 处理 choice...</span></div></div><div><div><div>6</div></div><div><span>} </span><span>while</span><span> (</span><span>choice</span><span> </span><span>!=</span><span> </span><span>0</span><span>);</span><span>      // 注意末尾分号</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 至少执行一次——天然适合"菜单系统"</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>for：计数循环<a href="#for计数循环"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 打印 1~10 的平方</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>10</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>"²= "</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>*</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 死循环的两种写法</span></div></div><div><div><div>7</div></div><div><span>for</span><span> (;;) {</span><span> /* ... */</span><span> }</span></div></div><div><div><div>8</div></div><div><span>while</span><span> (</span><span>true</span><span>) {</span><span> /* ... */</span><span> }</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// for 的三个部分都可空：分号不能省</span></div></div><div><div><div>11</div></div><div><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>12</div></div><div><span>for</span><span> (; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>5</span><span>;) {</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>++</span><span>i</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>范围 for + auto（C++11，遍历首选）<a href="#范围-for--autoc11遍历首选"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>arr</span><span>[]{</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>};</span></div></div><div><div><div>7</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>x</span><span> : </span><span>arr</span><span>)</span><span>                    // 遍历数组</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>x</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span><span>           // 10 20 30 40</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;std::</span><span>string</span><span>&gt; </span><span>langs</span><span>{</span><span>"C++"</span><span>, </span><span>"Python"</span><span>, </span><span>"Java"</span><span>};</span></div></div><div><div><div>12</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>lang</span><span> : </span><span>langs</span><span>)</span><span>       // 只读遍历用 const auto&amp;（免拷贝）</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>lang</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>"Cyber"</span><span>;</span></div></div><div><div><div>17</div></div><div><span>    </span><span>for</span><span> (</span><span>char</span><span> </span><span>c</span><span> : </span><span>s</span><span>)</span><span>                     // 遍历字符串</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span> </span><span>&lt;&lt;</span><span> </span><span>"-"</span><span>;</span></div></div><div><div><div>19</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>遍历三姿势</strong>：</p>

<table><thead><tr><th>写法</th><th>语义</th><th>适用</th></tr></thead><tbody><tr><td><code>for (auto x : c)</code></td><td>拷贝每个元素</td><td>小对象/基本类型</td></tr><tr><td><code>for (auto&amp; x : c)</code></td><td>引用，可修改元素</td><td>要改内容</td></tr><tr><td><code>for (const auto&amp; x : c)</code></td><td>只读引用，零拷贝</td><td>大对象只读（默认选它）</td></tr></tbody></table></section></section>
<section><h2>三、break / continue<a href="#三break--continue"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// break：终止所在层循环</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>100</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span> (</span><span>i</span><span> </span><span>*</span><span> </span><span>i</span><span> </span><span>&gt;</span><span> </span><span>500</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"第一个平方超500的是 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>5</div></div><div><span>        </span><span>break</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// continue：跳过本次</span></div></div><div><div><div>10</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>20</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>if</span><span> (</span><span>i</span><span> </span><span>%</span><span> </span><span>3</span><span> </span><span>==</span><span> </span><span>0</span><span>) </span><span>continue</span><span>;</span><span>    // 跳过 3 的倍数</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span><span>       // 1 2 4 5 7 8 ...</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>C++ 没有 Python 的”循环 else”，等价逻辑用一个标志变量实现。</p></section>
<section><h2>四、嵌套循环与经典练习<a href="#四嵌套循环与经典练习"><span>#</span></a></h2><section><h3>1. 九九乘法表<a href="#1-九九乘法表"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>9</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>j</span><span> </span><span>&lt;=</span><span> </span><span>i</span><span>; </span><span>++</span><span>j</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>printf</span><span>(</span><span>"</span><span>%d</span><span>×</span><span>%d</span><span>=</span><span>%-4d</span><span>"</span><span>, </span><span>j</span><span>, </span><span>i</span><span>, </span><span>i</span><span> </span><span>*</span><span> </span><span>j</span><span>);</span><span>   // %-4d 左对齐宽4</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 判断质数（带输入校验）<a href="#2-判断质数带输入校验"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;cmath&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>bool</span><span> </span><span>is_prime</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>) {</span></span><span>                 // bool 函数，第五篇详讲</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> (</span><span>n</span><span> </span><span>&lt;</span><span> </span><span>2</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>2</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> std::</span><span>sqrt</span><span>(</span><span>n</span><span>); </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>        </span><span>if</span><span> (</span><span>n</span><span> </span><span>%</span><span> </span><span>i</span><span> </span><span>==</span><span> </span><span>0</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span> </span><span>&lt;&lt;</span><span> (</span><span>is_prime</span><span>(</span><span>n</span><span>) </span><span>?</span><span> </span><span>" 是"</span><span> </span><span>:</span><span> </span><span>" 不是"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"质数</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>3. 打印图形（嵌套循环的空间感）<a href="#3-打印图形嵌套循环的空间感"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 金字塔（5行）</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>rows</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>rows</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>s</span><span> </span><span>&lt;</span><span> </span><span>rows</span><span> </span><span>-</span><span> </span><span>i</span><span>; </span><span>++</span><span>s</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span><span>   // 左侧空格</span></div></div><div><div><div>5</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>2</span><span> </span><span>*</span><span> </span><span>i</span><span> </span><span>-</span><span> </span><span>1</span><span>; </span><span>++</span><span>j</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"*"</span><span>;</span><span>  // 星号</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>//     *</span></div></div><div><div><div>9</div></div><div><span>//    ***</span></div></div><div><div><div>10</div></div><div><span>//   *****</span></div></div><div><div><div>11</div></div><div><span>//  *******</span></div></div><div><div><div>12</div></div><div><span>// *********</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 猜数字（do-while 的主场）<a href="#4-猜数字do-while-的主场"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;cstdlib&gt;</span><span>      </span><span>// rand/srand</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;ctime&gt;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>srand</span><span><span>(</span><span>std</span><span>::</span></span><span>time</span><span>(</span><span>nullptr</span><span>));</span><span>        // 播种子</span></div></div><div><div><div>7</div></div><div><span>    </span><span>int</span><span> </span><span>answer</span><span> </span><span>=</span><span> std::</span><span>rand</span><span>() </span><span>%</span><span> </span><span>100</span><span> </span><span>+</span><span> </span><span>1</span><span>;</span><span>    // 1~100</span></div></div><div><div><div>8</div></div><div><span>    </span><span>int</span><span> </span><span>guess</span><span>, </span><span>tries</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>do</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"猜(1-100): "</span><span>;</span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span> (</span><span>!</span><span>(std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>guess</span><span>)) {</span><span>        // 输入校验（上篇）</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>std::</span><span>cin</span><span>.</span><span>clear</span><span>();</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>std::</span><span>cin</span><span>.</span><span>ignore</span><span>(</span><span>10000</span><span>, </span><span>'</span><span>\n</span><span>'</span><span>);</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"请输入数字！</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>16</div></div><div><span>            </span><span>continue</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>        </span><span>++</span><span>tries</span><span>;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>if</span><span> (</span><span>guess</span><span> </span><span>&lt;</span><span> </span><span>answer</span><span>)      std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"小了</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>20</div></div><div><span>        </span><span>else</span><span> </span><span>if</span><span> (</span><span>guess</span><span> </span><span>&gt;</span><span> </span><span>answer</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"大了</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>21</div></div><div><span>        </span><span>else</span><span>                     std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"对了！用了 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>tries</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 次</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>} </span><span>while</span><span> (</span><span>guess</span><span> </span><span>!=</span><span> </span><span>answer</span><span>);</span></div></div><div><div><div>23</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>5. FizzBuzz（面试名题）<a href="#5-fizzbuzz面试名题"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>30</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span> (</span><span>i</span><span> </span><span>%</span><span> </span><span>15</span><span> </span><span>==</span><span> </span><span>0</span><span>)      std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"FizzBuzz "</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>else</span><span> </span><span>if</span><span> (</span><span>i</span><span> </span><span>%</span><span> </span><span>3</span><span> </span><span>==</span><span> </span><span>0</span><span>)  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Fizz "</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>else</span><span> </span><span>if</span><span> (</span><span>i</span><span> </span><span>%</span><span> </span><span>5</span><span> </span><span>==</span><span> </span><span>0</span><span>)  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Buzz "</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>else</span><span>                  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、goto：知道但别用<a href="#五goto知道但别用"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>    </span></span><span>// C++ 保留了 goto，但现代编码规范一律禁用——破坏结构化、难以追踪</span></div></div><div><div><div>2</div></div><div><span>    </span><span>goto</span><span> </span><span>end</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"这行被跳过"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>end</span><span>:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>唯一”合理”场景是多层嵌套循环的一次性跳出，但那也该用函数 + return 重构。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>输入一个整数，逆序输出各位数字（1234 → 4321；while + % /）</li>
<li>求两个数的最大公约数（辗转相除：while ((b %= a %= b) …) 或标准三行版）</li>
<li>打印 100~999 的所有水仙花数（各位立方和等于自身）</li>
<li>用范围 for 统计 <code>std::vector&lt;int&gt;{3,7,1,9,4}</code> 的最大值、最小值与平均值</li>
<li>双重循环找”百钱买百鸡”：公鸡5元/只、母鸡3元/只、小鸡1元3只，100元买100只，输出所有方案</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>if 条件必带括号；switch 只认整型/枚举、必带 break 与 default</li>
<li>while 先判后做、do-while 先做后判（菜单场景）、for 三段式</li>
<li>范围 for + <code>const auto&amp;</code> 是遍历容器的默认姿势</li>
<li>break 跳出本层、continue 跳过本次；没有循环 else</li>
<li>goto 是历史遗迹，现代 C++ 禁用</li>
</ul><p><strong>下一篇</strong>：函数——定义、声明、重载与默认参数，C++ 的函数比 Python 讲究得多。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。五个经典练习建议全部独立敲一遍，比看十遍教程有效。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-04/</id>
      <title type="text">C++ 入门教程（四）：函数详解</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-04/"/>
      <summary type="text">深入 C++ 函数：声明与定义分离、参数传递三种方式（值/引用/指针）、默认参数与函数重载、内联与递归、作用域与生命周期、头文件组织，配工资计算器与斐波那契实战。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>C++ 的函数体系比 Python 严格也强大：<strong>函数必须先声明后使用</strong>、参数传递方式直接决定性能与语义、还有重载与默认参数两大利器。本篇一次讲透，这是 C++ 分水岭之一。</p></section>
<section><h2>一、定义、声明与头文件<a href="#一定义声明与头文件"><span>#</span></a></h2><section><h3>为什么需要”先声明”<a href="#为什么需要先声明"><span>#</span></a></h3><p>编译器从上往下读文件，调用函数前必须”见过”它。大项目里函数分散在多文件，靠**声明（原型）**解决：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 函数声明（原型）：告诉编译器"有这个函数，长这样"</span></div></div><div><div><div>2</div></div><div><span>double</span><span> </span><span>calc_bmi</span><span>(</span><span>double</span><span><span> </span><span>weight</span><span>, </span></span><span>double</span><span><span> </span><span>height</span><span>);</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>calc_bmi</span><span>(</span><span>70</span><span>, </span><span>1.75</span><span>);</span><span>    // ✓ 编译器已认识它</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 函数定义：真正实现</span></div></div><div><div><div>10</div></div><div><span>double</span><span> </span><span>calc_bmi</span><span>(</span><span>double</span><span><span> </span><span>weight</span><span>, </span></span><span>double</span><span><span> </span><span>height</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>return</span><span> </span><span>weight</span><span> </span><span>/</span><span> (</span><span>height</span><span> </span><span>*</span><span> </span><span>height</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>声明与定义的区别</strong>：声明是”预告”（无函数体），定义是”实现”。声明可多次，定义只能一次。</p></section><section><h3>多文件组织（.h / .cpp）<a href="#多文件组织h--cpp"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ===== math_utils.h（头文件：放声明）=====</span></div></div><div><div><div>2</div></div><div><span>#ifndef</span><span> </span><span>MATH_UTILS_H</span><span>          // 包含保护：防止重复包含</span></div></div><div><div><div>3</div></div><div><span>#define</span><span> </span><span>MATH_UTILS_H</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>double</span><span> </span><span>calc_bmi</span><span>(</span><span>double</span><span><span> </span><span>weight</span><span>, </span></span><span>double</span><span><span> </span><span>height</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>bool</span><span>   </span><span>is_prime</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>);</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>#endif</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ===== math_utils.cpp（源文件：放定义）=====</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>"math_utils.h"</span><span>       </span><span>// 自己的头文件用 ""</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>double</span><span> </span><span>calc_bmi</span><span>(</span><span>double</span><span><span> </span><span>weight</span><span>, </span></span><span>double</span><span><span> </span><span>height</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>weight</span><span> </span><span>/</span><span> (</span><span>height</span><span> </span><span>*</span><span> </span><span>height</span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>bool</span><span> </span><span>is_prime</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span> (</span><span>n</span><span> </span><span>&lt;</span><span> </span><span>2</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>10</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>2</span><span>; </span><span>i</span><span> </span><span>*</span><span> </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>n</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span> (</span><span>n</span><span> </span><span>%</span><span> </span><span>i</span><span> </span><span>==</span><span> </span><span>0</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>12</div></div><div><span>    </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ===== main.cpp =====</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>"math_utils.h"</span><span>       </span><span>// 用谁的头文件就 include 谁</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>calc_bmi</span><span>(</span><span>70</span><span>, </span><span>1.75</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译：<code>g++ main.cpp math_utils.cpp -o app</code>（所有 cpp 都要参与编译）。</p></section></section>
<section><h2>二、参数传递：C++ 的灵魂<a href="#二参数传递c-的灵魂"><span>#</span></a></h2><section><h3>1. 值传递（默认）：拷贝一份<a href="#1-值传递默认拷贝一份"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>try_change</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>) {</span></span><span>      // x 是实参的副本</span></div></div><div><div><div>2</div></div><div><span>    </span><span>x</span><span> </span><span>=</span><span> </span><span>100</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>try_change</span><span>(</span><span>n</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span>;</span><span>           // 5 —— 原值不变</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 引用传递（&amp;）：起别名，可修改原值<a href="#2-引用传递起别名可修改原值"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>actually_change</span><span>(</span><span>int&amp;</span><span><span> </span><span>x</span><span>) {</span></span><span>    // x 是 n 的别名</span></div></div><div><div><div>2</div></div><div><span>    </span><span>x</span><span> </span><span>=</span><span> </span><span>100</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>actually_change</span><span>(</span><span>n</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span>;</span><span>           // 100 ✓ 改的是原值</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>引用的经典用途 1：多返回值（出参）</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 同时返回商和余数</span></div></div><div><div><div>2</div></div><div><span>void</span><span> </span><span>divmod</span><span>(</span><span>int</span><span><span> </span><span>a</span><span>, </span></span><span>int</span><span><span> </span><span>b</span><span>, </span></span><span>int&amp;</span><span><span> </span><span>quotient</span><span>, </span></span><span>int&amp;</span><span><span> </span><span>remainder</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>quotient</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>/</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>remainder</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>%</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>int</span><span> </span><span>q</span><span>, </span><span>r</span><span>;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>divmod</span><span>(</span><span>17</span><span>, </span><span>5</span><span>, </span><span>q</span><span>, </span><span>r</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>q</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 余 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>r</span><span>;</span><span>    // 3 余 2</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. const 引用传递：大对象只读零拷贝<a href="#3-const-引用传递大对象只读零拷贝"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// 值传递会拷贝整个字符串（浪费）；const&amp; 既不拷贝又不可改</span></div></div><div><div><div>4</div></div><div><span>void</span><span> </span><span>print_banner</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>text</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"==== "</span><span> </span><span>&lt;&lt;</span><span> </span><span>text</span><span> </span><span>&lt;&lt;</span><span> </span><span>" ====</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>参数传递决策表</strong>：</p>

<table><thead><tr><th>参数类型</th><th>写法</th><th>场景</th></tr></thead><tbody><tr><td>小对象（int/double/指针）</td><td>值传递 <code>T x</code></td><td>默认</td></tr><tr><td>要修改实参</td><td>引用 <code>T&amp; x</code></td><td>出参、原地修改</td></tr><tr><td>大对象只读（string/vector）</td><td><code>const T&amp; x</code></td><td>默认</td></tr><tr><td>可能为空/要改指向</td><td>指针 <code>T* x</code>（第六篇）</td><td>C 风格接口</td></tr></tbody></table></section><section><h3>默认参数<a href="#默认参数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>double</span><span> </span><span>power</span><span>(</span><span>double</span><span><span> </span><span>base</span><span>, </span></span><span>int</span><span><span> </span><span>exp</span><span> </span></span><span>=</span><span> </span><span>2</span><span>);</span><span>     // 声明处给默认值</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>power</span><span>(</span><span>3</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>          // 9（用默认 exp=2）</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>power</span><span>(</span><span>3</span><span>, </span><span>3</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 27</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>double</span><span> </span><span>power</span><span>(</span><span>double</span><span><span> </span><span>base</span><span>, </span></span><span>int</span><span><span> </span><span>exp</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>double</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>10</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>exp</span><span>; </span><span>++</span><span>i</span><span>) </span><span>result</span><span> </span><span>*=</span><span> </span><span>base</span><span>;</span></div></div><div><div><div>11</div></div><div><span>    </span><span>return</span><span> </span><span>result</span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>规矩</strong>：默认参数必须从右往左连续给——<code>f(int a, int b=1, int c=2)</code> ✓，<code>f(int a=1, int b)</code> ❌。声明与定义分离时，默认值只能写在<strong>声明</strong>里。</p></section></section>
<section><h2>三、函数重载（Overload）<a href="#三函数重载overload"><span>#</span></a></h2><p>同名函数、参数不同（个数或类型），编译器按实参自动匹配：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span>    </span><span>max_of</span><span>(</span><span>int</span><span><span> </span><span>a</span><span>, </span></span><span>int</span><span><span> </span><span>b</span><span>)             { </span></span><span>return</span><span> </span><span>a</span><span> </span><span>&gt;</span><span> </span><span>b</span><span> </span><span>?</span><span> </span><span>a</span><span> </span><span>:</span><span> </span><span>b</span><span>; }</span></div></div><div><div><div>5</div></div><div><span>double</span><span> </span><span>max_of</span><span>(</span><span>double</span><span><span> </span><span>a</span><span>, </span></span><span>double</span><span><span> </span><span>b</span><span>)       { </span></span><span>return</span><span> </span><span>a</span><span> </span><span>&gt;</span><span> </span><span>b</span><span> </span><span>?</span><span> </span><span>a</span><span> </span><span>:</span><span> </span><span>b</span><span>; }</span></div></div><div><div><div>6</div></div><div><span>int</span><span>    </span><span>max_of</span><span>(</span><span>int</span><span><span> </span><span>a</span><span>, </span></span><span>int</span><span><span> </span><span>b</span><span>, </span></span><span>int</span><span><span> </span><span>c</span><span>)      { </span></span><span>return</span><span> </span><span>max_of</span><span>(</span><span>max_of</span><span>(</span><span>a</span><span>, </span><span>b</span><span>), </span><span>c</span><span>); }</span></div></div><div><div><div>7</div></div><div><span>std::</span><span>string</span><span> </span><span>max_of</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>b</span><span>) { </span></span><span>return</span><span> </span><span>a</span><span> </span><span>&gt;</span><span> </span><span>b</span><span> </span><span>?</span><span> </span><span>a</span><span> </span><span>:</span><span> </span><span>b</span><span>; }</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>max_of</span><span>(</span><span>3</span><span>, </span><span>7</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>            // int 版 → 7</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>max_of</span><span>(</span><span>3.14</span><span>, </span><span>2.71</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // double 版 → 3.14</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>max_of</span><span>(</span><span>1</span><span>, </span><span>9</span><span>, </span><span>4</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>         // 三参版 → 9</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>max_of</span><span>(</span><span>"apple"</span><span>, </span><span>"banana"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span> // string 版 → banana</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>重载只看<strong>参数</strong>，不看返回值——<code>int f()</code> 与 <code>double f()</code> 不构成重载，直接编译错误。
Python 没有重载（用默认参数模拟），这是 C++ 的”编译期多态”。</p></div></div></section>
<section><h2>四、递归<a href="#四递归"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>unsigned</span><span> </span><span>long</span><span> </span><span>long</span><span> </span><span>factorial</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>n</span><span> </span><span>&lt;=</span><span> </span><span>1</span><span>) </span><span>return</span><span> </span><span>1</span><span>;</span><span>                       // 基线</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>n</span><span> </span><span>*</span><span> </span><span>factorial</span><span>(</span><span>n</span><span> </span><span>-</span><span> </span><span>1</span><span>);</span><span>                // 递推</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 输出斐波那契第 n 项（递归版——直观但慢）</span></div></div><div><div><div>9</div></div><div><span>long</span><span> </span><span>long</span><span> </span><span>fib</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span> (</span><span>n</span><span> </span><span>&lt;</span><span> </span><span>2</span><span>) </span><span>return</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>11</div></div><div><span>    </span><span>return</span><span> </span><span>fib</span><span>(</span><span>n</span><span> </span><span>-</span><span> </span><span>1</span><span>) </span><span>+</span><span> </span><span>fib</span><span>(</span><span>n</span><span> </span><span>-</span><span> </span><span>2</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>10</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>factorial</span><span>(</span><span>i</span><span>) </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>fib</span><span>(</span><span>40</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 102334155（已经要跑一会儿了）</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>注意 <code>unsigned long long</code>：20! 已超 int 范围，选对类型是 C++ 的日常。</p></section>
<section><h2>五、作用域与生命周期<a href="#五作用域与生命周期"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>g</span><span> </span><span>=</span><span> </span><span>100</span><span>;</span><span>                    // 全局变量（尽量少用）</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>void</span><span> </span><span>demo</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>local</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span><span>              // 局部：函数结束销毁</span></div></div><div><div><div>7</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>count</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>       // 静态局部：只初始化一次，函数间保留</span></div></div><div><div><div>8</div></div><div><span>    </span><span>++</span><span>count</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"local="</span><span> </span><span>&lt;&lt;</span><span> </span><span>local</span><span>++</span><span> </span><span>&lt;&lt;</span><span> </span><span>" count="</span><span> </span><span>&lt;&lt;</span><span> </span><span>count</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>demo</span><span>();</span><span>    // local=1 count=1</span></div></div><div><div><div>14</div></div><div><span>    </span><span>demo</span><span>();</span><span>    // local=1 count=2（local 每次重建，count 保留！）</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>16</div></div><div><span>        </span><span>int</span><span> </span><span>block_var</span><span> </span><span>=</span><span> </span><span>42</span><span>;</span><span>     // 块作用域</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>// std::cout &lt;&lt; block_var;  // ❌ 出块即亡</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>static</code> 局部变量 = “只属于这个函数的全局变量”，常用于调用计数、缓存。</p></section>
<section><h2>六、内联函数与 constexpr 函数<a href="#六内联函数与-constexpr-函数"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// inline：建议编译器把函数体直接展开到调用处（省调用开销）</span></div></div><div><div><div>2</div></div><div><span>// 现代编译器很聪明，inline 更多语义是"允许多文件安全定义"</span></div></div><div><div><div>3</div></div><div><span>inline</span><span> </span><span>int</span><span> </span><span>square</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>) { </span></span><span>return</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>x</span><span>; }</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// constexpr 函数（C++11/14）：可在编译期求值</span></div></div><div><div><div>6</div></div><div><span>constexpr</span><span> </span><span>int</span><span> </span><span>cube</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>) { </span></span><span>return</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>x</span><span>; }</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>int</span><span> </span><span>arr</span><span>[</span><span>cube</span><span>(</span><span>3</span><span>)];</span><span>          // ✓ 27 作为编译期数组大小</span></div></div><div><div><div>9</div></div><div><span>constexpr</span><span> </span><span>int</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>cube</span><span>(</span><span>4</span><span>);</span><span> // 编译期计算出 64</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>七、实战：个税与工资计算器<a href="#七实战个税与工资计算器"><span>#</span></a></h2><p>综合本篇知识（声明分离、引用出参、重载、默认参数）：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;iomanip&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// ===== salary.h 的声明部分（这里合并演示）=====</span></div></div><div><div><div>5</div></div><div><span>double</span><span> </span><span>calc_tax</span><span>(</span><span>double</span><span><span> </span><span>taxable</span><span>);</span></span><span>                       // 按超额累进</span></div></div><div><div><div>6</div></div><div><span>void</span><span>   </span><span>split_salary</span><span>(</span><span>double</span><span><span> </span><span>gross</span><span>, </span></span><span>double&amp;</span><span><span> </span><span>net</span><span>, </span></span><span>double&amp;</span><span><span> </span><span>tax</span><span>);</span></span><span>   // 出参</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// ===== 实现 =====</span></div></div><div><div><div>9</div></div><div><span>double</span><span> </span><span>calc_tax</span><span>(</span><span>double</span><span><span> </span><span>taxable</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>// 简化版超额累进（月度，免征额已扣除）</span></div></div><div><div><div>11</div></div><div><span>    </span><span>if</span><span> (</span><span>taxable</span><span> </span><span>&lt;=</span><span> </span><span>0</span><span>)    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>12</div></div><div><span>    </span><span>if</span><span> (</span><span>taxable</span><span> </span><span>&lt;=</span><span> </span><span>3000</span><span>) </span><span>return</span><span> </span><span>taxable</span><span> </span><span>*</span><span> </span><span>0.03</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>if</span><span> (</span><span>taxable</span><span> </span><span>&lt;=</span><span> </span><span>12000</span><span>) </span><span>return</span><span> </span><span>3000</span><span> </span><span>*</span><span> </span><span>0.03</span><span> </span><span>+</span><span> (</span><span>taxable</span><span> </span><span>-</span><span> </span><span>3000</span><span>) </span><span>*</span><span> </span><span>0.10</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>return</span><span> </span><span>3000</span><span> </span><span>*</span><span> </span><span>0.03</span><span> </span><span>+</span><span> </span><span>9000</span><span> </span><span>*</span><span> </span><span>0.10</span><span> </span><span>+</span><span> (</span><span>taxable</span><span> </span><span>-</span><span> </span><span>12000</span><span>) </span><span>*</span><span> </span><span>0.20</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>void</span><span> </span><span>split_salary</span><span>(</span><span>double</span><span><span> </span><span>gross</span><span>, </span></span><span>double&amp;</span><span><span> </span><span>net</span><span>, </span></span><span>double&amp;</span><span><span> </span><span>tax</span><span>) {</span></span></div></div><div><div><div>18</div></div><div><span>    </span><span>tax</span><span> </span><span>=</span><span> </span><span>calc_tax</span><span>(</span><span>gross</span><span> </span><span>-</span><span> </span><span>5000.0</span><span>);</span><span>      // 免征额 5000</span></div></div><div><div><div>19</div></div><div><span>    </span><span>net</span><span> </span><span>=</span><span> </span><span>gross</span><span> </span><span>-</span><span> </span><span>tax</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>double</span><span> </span><span>gross</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>fixed</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>setprecision</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>25</div></div><div><span>    </span><span>while</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>输入税前月薪（0退出）: "</span><span>;</span></div></div><div><div><div>27</div></div><div><span>        </span><span>if</span><span> (</span><span>!</span><span>(std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>gross</span><span>)) </span><span>break</span><span>;</span></div></div><div><div><div>28</div></div><div><span>        </span><span>if</span><span> (</span><span>gross</span><span> </span><span>&lt;=</span><span> </span><span>0</span><span>) </span><span>break</span><span>;</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>        </span><span>double</span><span> </span><span>net</span><span>, </span><span>tax</span><span>;</span></div></div><div><div><div>31</div></div><div><span>        </span><span>split_salary</span><span>(</span><span>gross</span><span>, </span><span>net</span><span>, </span><span>tax</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"税前: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>gross</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>税额: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>tax</span></div></div><div><div><div>33</div></div><div><span>                  </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>到手: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>net</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写 <code>swap(int&amp;, int&amp;)</code> 验证引用交换；再写值传递版对比为什么不行</li>
<li>重载 <code>area</code>：正方形（1 参）、长方形（2 参）、圆（半径，double 参）</li>
<li>写 <code>void stats(const std::vector&lt;int&gt;&amp; v, double&amp; avg, int&amp; max_v, int&amp; min_v)</code> 一次算三个统计量</li>
<li>递归实现”数字倒序打印”：<code>print_digits(1234)</code> 输出 <code>4 3 2 1</code></li>
<li>把本篇工资计算器拆成 salary.h / salary.cpp / main.cpp 三文件编译通过</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>声明与定义分离；头文件放声明（含包含保护），源文件放实现</li>
<li>值传递拷贝、<code>T&amp;</code> 可修改实参、<code>const T&amp;</code> 大对象只读零拷贝</li>
<li>默认参数靠右、写在声明处；重载按参数区分、与返回值无关</li>
<li>static 局部变量跨调用保留；递归必须有基线</li>
<li>inline/constexpr 提示编译期优化</li>
</ul><p><strong>下一篇</strong>：数组与 std::string/vector 三剑客——C++ 数据容器的正确打开方式。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。“声明放头文件”是多文件编程的第一课，练习 5 必做。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-05/</id>
      <title type="text">C++ 入门教程（五）：数组与字符串</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-05/"/>
      <summary type="text">详解 C 风格数组的局限与二维数组、std::vector 的增删改查全家桶、std::string 的构造与常用操作、C 字符串与 string 互转，掌握现代 C++ 容器优先原则。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>存”一堆数据”的三个层次：<strong>C 数组</strong>（原始、固定大小）、<strong>std::vector</strong>（动态数组，现代首选）、<strong>std::string</strong>（字符串专用容器）。重点放在后两者——现代 C++ 的原则是”能用 vector 不用数组，能用 string 不用 char*”。</p></section>
<section><h2>一、C 风格数组<a href="#一c-风格数组"><span>#</span></a></h2><section><h3>一维数组<a href="#一维数组"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>int</span><span> </span><span>scores</span><span>[</span><span>5</span><span>] </span><span>=</span><span> {</span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>};</span><span>   // 定义即初始化</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>zeros</span><span>[</span><span>10</span><span>] </span><span>=</span><span> {};</span><span>                      // 全部初始化为 0</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int</span><span> </span><span>partial</span><span>[</span><span>5</span><span>] </span><span>=</span><span> {</span><span>1</span><span>, </span><span>2</span><span>};</span><span>                 // {1,2,0,0,0} 其余补 0</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>// 访问与修改（下标从 0 开始）</span></div></div><div><div><div>9</div></div><div><span>    </span><span>scores</span><span>[</span><span>0</span><span>] </span><span>=</span><span> </span><span>95</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>scores</span><span>[</span><span>4</span><span>] </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>          // 66</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>// 数组大小（仅对"本作用域数组"有效）</span></div></div><div><div><div>13</div></div><div><span>    </span><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>sizeof</span><span>(</span><span>scores</span><span>) </span><span>/</span><span> </span><span>sizeof</span><span>(</span><span>scores</span><span>[</span><span>0</span><span>]);</span><span>   // 5</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>// 遍历</span></div></div><div><div><div>16</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>n</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>scores</span><span>[</span><span>i</span><span>] </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>x</span><span> : </span><span>scores</span><span>)</span><span>                     // 范围 for 更优雅</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>x</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>22</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>数组的两大天生局限</strong>：</p><ol>
<li><strong>大小编译期固定</strong>：<code>int arr[n]</code>（n 是变量）不是标准 C++（部分编译器扩展支持）</li>
<li><strong>不记录长度</strong>：传给函数后退化成”裸指针”，sizeof 失效</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>print_arr</span><span>(</span><span>int</span><span><span> </span><span>arr</span><span>[], </span></span><span>int</span><span><span> </span><span>size</span><span>) {</span></span><span>        // 数组参数必须附带长度</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>// sizeof(arr) 在这里是指针大小（8），不是数组大小！</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>size</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>arr</span><span>[</span><span>i</span><span>] </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>数组<strong>不检查越界</strong>：<code>scores[100]</code> 编译运行都不报错，直接读写非法内存——未定义行为，可能是乱码、崩溃或安全漏洞。这是 C/C++ 缓冲区溢出漏洞的根源。</p></div></div></section><section><h3>二维数组<a href="#二维数组"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>matrix</span><span>[</span><span>3</span><span>][</span><span>4</span><span>] </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>{</span><span>1</span><span>,  </span><span>2</span><span>,  </span><span>3</span><span>,  </span><span>4</span><span>},</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>{</span><span>5</span><span>,  </span><span>6</span><span>,  </span><span>7</span><span>,  </span><span>8</span><span>},</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>{</span><span>9</span><span>, </span><span>10</span><span>, </span><span>11</span><span>, </span><span>12</span><span>},</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>rows</span><span> </span><span>=</span><span> </span><span>3</span><span>, </span><span>cols</span><span> </span><span>=</span><span> </span><span>4</span><span>;</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>rows</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>cols</span><span>; </span><span>++</span><span>j</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>matrix</span><span>[</span><span>i</span><span>][</span><span>j</span><span>] </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\t</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 打擂台找最大值及其位置</span></div></div><div><div><div>15</div></div><div><span>int</span><span> </span><span>max_v</span><span> </span><span>=</span><span> </span><span>matrix</span><span>[</span><span>0</span><span>][</span><span>0</span><span>], </span><span>mi</span><span> </span><span>=</span><span> </span><span>0</span><span>, </span><span>mj</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>16</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>rows</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>17</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>cols</span><span>; </span><span>++</span><span>j</span><span>)</span></div></div><div><div><div>18</div></div><div><span>        </span><span>if</span><span> (</span><span>matrix</span><span>[</span><span>i</span><span>][</span><span>j</span><span>] </span><span>&gt;</span><span> </span><span>max_v</span><span>) {</span></div></div><div><div><div>19</div></div><div><span>            </span><span>max_v</span><span> </span><span>=</span><span> </span><span>matrix</span><span>[</span><span>i</span><span>][</span><span>j</span><span>]; </span><span>mi</span><span> </span><span>=</span><span> </span><span>i</span><span>; </span><span>mj</span><span> </span><span>=</span><span> </span><span>j</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"最大 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>max_v</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 在 ("</span><span> </span><span>&lt;&lt;</span><span> </span><span>mi</span><span> </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>mj</span><span> </span><span>&lt;&lt;</span><span> </span><span>")</span><span>\n</span><span>"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>二、std::vector：动态数组（现代首选）<a href="#二stdvector动态数组现代首选"><span>#</span></a></h2><section><h3>构造与基本操作<a href="#构造与基本操作"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v1</span><span>;</span><span>                      // 空</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v2</span><span>(</span><span>5</span><span>);</span><span>                   // {0,0,0,0,0}</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v3</span><span>(</span><span>5</span><span>, </span><span>7</span><span>);</span><span>                // {7,7,7,7,7}</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v4</span><span> </span><span>=</span><span> {</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>};</span><span>       // 列表初始化</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;std::</span><span>string</span><span>&gt; </span><span>names</span><span>{</span><span>"小明"</span><span>, </span><span>"小红"</span><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v4</span><span>.</span><span>size</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>           // 4  元素数</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v4</span><span>.</span><span>empty</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>          // 0  是否为空</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>v4</span><span>[</span><span>0</span><span>] </span><span>=</span><span> </span><span>100</span><span>;</span><span>                              // 修改（同样不查越界）</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v4</span><span>.</span><span>at</span><span>(</span><span>1</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>            // 2  at() 会检查越界并抛异常</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v4</span><span>.</span><span>front</span><span>() </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>v4</span><span>.</span><span>back</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>  // 100 4</span></div></div><div><div><div>17</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>增删<a href="#增删"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>vector</span><span>&lt;int&gt;</span><span> </span><span>v</span><span> </span><span>=</span><span> {</span><span>2</span><span>, </span><span>3</span><span>};</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>v</span><span>.</span><span>push_back</span><span>(</span><span>4</span><span>);</span><span>               // 尾部追加：{2,3,4}   —— 最高频操作</span></div></div><div><div><div>4</div></div><div><span>v</span><span>.</span><span>insert</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>1</span><span>);</span><span>       // 头部插入：{1,2,3,4}</span></div></div><div><div><div>5</div></div><div><span>v</span><span>.</span><span>insert</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>2</span><span>, </span><span>99</span><span>);</span><span>  // 指定位置：{1,2,99,3,4}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>v</span><span>.</span><span>pop_back</span><span>();</span><span>                 // 删除尾部：{1,2,99,3}</span></div></div><div><div><div>8</div></div><div><span>v</span><span>.</span><span>erase</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>2</span><span>);</span><span>       // 删除指定位置：{1,2,3}</span></div></div><div><div><div>9</div></div><div><span>v</span><span>.</span><span>erase</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>begin</span><span>() </span><span>+</span><span> </span><span>2</span><span>);</span><span>   // 删除区间：{3}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>v</span><span>.</span><span>clear</span><span>();</span><span>                    // 清空：{}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>性能提示</strong>：push_back 尾部均摊 O(1)；insert/erase 中间是 O(n)——频繁中间插删的场景后续用 list（进阶）。</p></section><section><h3>遍历与修改<a href="#遍历与修改"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>vector</span><span>&lt;int&gt;</span><span> </span><span>v</span><span> </span><span>=</span><span> {</span><span>5</span><span>, </span><span>3</span><span>, </span><span>8</span><span>, </span><span>1</span><span>, </span><span>9</span><span>};</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// ① 下标循环（需要下标时）</span></div></div><div><div><div>4</div></div><div><span>for</span><span> (std::</span><span>size_t</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>v</span><span>.</span><span>size</span><span>(); </span><span>++</span><span>i</span><span>)</span><span>   // size() 返回无符号 size_t</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>[</span><span>i</span><span>] </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// ② 范围 for 只读</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>x</span><span> : </span><span>v</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>x</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// ③ 范围 for 修改</span></div></div><div><div><div>11</div></div><div><span>for</span><span> (</span><span>auto&amp;</span><span> </span><span>x</span><span> : </span><span>v</span><span>) </span><span>x</span><span> </span><span>*=</span><span> </span><span>2</span><span>;</span><span>             // 全部翻倍</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 已知量小或有符号运算时，int i 配 static_cast：</span></div></div><div><div><div>14</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span><span>static_cast</span><span>&lt;int&gt;</span></span><span>(</span><span>v</span><span>.</span><span>size</span><span>()); </span><span>++</span><span>i</span><span>) {</span><span> /* ... */</span><span> }</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>动态增长的实力<a href="#动态增长的实力"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>vector</span><span>&lt;int&gt;</span><span> </span><span>v</span><span>;</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>i</span><span> </span><span>&lt;=</span><span> </span><span>100</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>v</span><span>.</span><span>push_back</span><span>(</span><span>i</span><span> </span><span>*</span><span> </span><span>i</span><span>);</span><span>        // 数组做不到的"边跑边长"</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>.</span><span>size</span><span>();</span><span>         // 100</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>排序与查找<a href="#排序与查找"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>vector</span><span>&lt;int&gt;</span><span> </span><span>v</span><span> </span><span>=</span><span> {</span><span>5</span><span>, </span><span>3</span><span>, </span><span>8</span><span>, </span><span>1</span><span>, </span><span>9</span><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span><span>              // 升序 {1,3,5,8,9}</span></div></div><div><div><div>6</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), std::</span><span>greater</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>   // 降序</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> std::</span><span>find</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>8</span><span>);</span><span> // 查找，返回迭代器</span></div></div><div><div><div>9</div></div><div><span>if</span><span> (</span><span>it</span><span> </span><span>!=</span><span> </span><span>v</span><span>.</span><span>end</span><span>())</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"找到，下标 "</span><span> </span><span>&lt;&lt;</span><span> (</span><span>it</span><span> </span><span>-</span><span> </span><span>v</span><span>.</span><span>begin</span><span>()) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 排序复杂数据（lambda 第四篇提过，第十篇详讲）</span></div></div><div><div><div>13</div></div><div><span>std::</span><span>vector</span><span>&lt;std::</span><span>pair</span><span>&lt;std::</span><span>string</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>st</span><span>{{</span><span>"小明"</span><span>,</span><span>90</span><span>},{</span><span>"小红"</span><span>,</span><span>92</span><span>}};</span></div></div><div><div><div>14</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>st</span><span>.</span><span>begin</span><span>(), </span><span>st</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>15</div></div><div><span><span>          </span></span><span>[](</span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>b</span><span>) { </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>second</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>.</span><span>second</span><span>; });</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>三、std::string 详解<a href="#三stdstring-详解"><span>#</span></a></h2><section><h3>构造与拼接<a href="#构造与拼接"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>string</span><span> </span><span>s1</span><span> </span><span>=</span><span> </span><span>"hello"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>string</span><span> </span><span>s2</span><span>(</span><span>"world"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>string</span><span> </span><span>s3</span><span>(</span><span>5</span><span>, </span><span>'a'</span><span>);</span><span>            // "aaaaa" 重复字符</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>string</span><span> </span><span>s4</span><span> </span><span>=</span><span> </span><span>s1</span><span> </span><span>+</span><span> </span><span>" "</span><span> </span><span>+</span><span> </span><span>s2</span><span>;</span><span>    // "hello world"（+ 随便拼）</span></div></div><div><div><div>7</div></div><div><span>s4</span><span> </span><span>+=</span><span> </span><span>"!"</span><span>;</span><span>                          // 追加</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 数值拼接需先转换（第二篇）：</span></div></div><div><div><div>10</div></div><div><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>11</div></div><div><span>std::</span><span>string</span><span> </span><span>info</span><span> </span><span>=</span><span> </span><span>"年龄: "</span><span> </span><span>+</span><span> std::</span><span>to_string</span><span>(</span><span>age</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>索引与常用方法<a href="#索引与常用方法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>string</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>"CyberPioneer"</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>size</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>         // 12（size 与 length 等价）</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>[</span><span>0</span><span>] </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>back</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span> // Cr</span></div></div><div><div><div>5</div></div><div><span>s</span><span>[</span><span>0</span><span>] </span><span>=</span><span> </span><span>'c'</span><span>;</span><span>                            // ✓ 可修改（不同于 Python！）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 子串：substr(起点, 长度)</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>substr</span><span>(</span><span>0</span><span>, </span><span>5</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // cyber</span></div></div><div><div><div>9</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>substr</span><span>(</span><span>5</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // Pioneer（到结尾）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 查找：find 找不到返回 string::npos</span></div></div><div><div><div>12</div></div><div><span>if</span><span> (</span><span>s</span><span>.</span><span>find</span><span>(</span><span>"Pioneer"</span><span>) </span><span>!=</span><span> std::string::</span><span>npos</span><span>)</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"包含 Pioneer，位置 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>find</span><span>(</span><span>"Pioneer"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>// 修改</span></div></div><div><div><div>16</div></div><div><span>std::</span><span>string</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>"  hi  "</span><span>;</span></div></div><div><div><div>17</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"|"</span><span> </span><span>&lt;&lt;</span><span> </span><span>t</span><span>.</span><span>substr</span><span>(</span><span>1</span><span>, </span><span>2</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"|</span><span>\n</span><span>"</span><span>;</span><span>   // 手动去空格（无现成 strip）</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>std::</span><span>string</span><span> </span><span>u</span><span> </span><span>=</span><span> </span><span>"a,b,c"</span><span>;</span></div></div><div><div><div>20</div></div><div><span>// 按","分割（STL 惯用法，sstream 第十一篇还会见）</span></div></div><div><div><div>21</div></div><div><span>#include</span><span> </span><span>&lt;sstream&gt;</span></div></div><div><div><div>22</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>std::</span><span>string</span><span>&gt;</span><span> </span><span>parts</span><span>;</span></div></div><div><div><div>23</div></div><div><span>std::</span><span>stringstream</span><span> </span><span>ss</span><span>(</span><span>u</span><span>);</span></div></div><div><div><div>24</div></div><div><span>std::</span><span>string</span><span> </span><span>item</span><span>;</span></div></div><div><div><div>25</div></div><div><span>while</span><span><span> (</span><span>std</span><span>::</span></span><span>getline</span><span>(</span><span>ss</span><span>, </span><span>item</span><span>, </span><span>','</span><span>))</span></div></div><div><div><div>26</div></div><div><span>    </span><span>parts</span><span>.</span><span>push_back</span><span>(</span><span>item</span><span>);</span><span>          // {"a","b","c"}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>比较<a href="#比较"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>string</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>"apple"</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>"banana"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>if</span><span> (</span><span>a</span><span> </span><span>==</span><span> </span><span>b</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"相等"</span><span>;</span></div></div><div><div><div>3</div></div><div><span>if</span><span> (</span><span>a</span><span> </span><span>&lt;</span><span> </span><span>b</span><span>)  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"a 在前"</span><span>;</span><span>   // 字典序，直接用比较运算符</span></div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>r</span><span> </span><span>=</span><span> </span><span>a</span><span>.</span><span>compare</span><span>(</span><span>b</span><span>);</span><span>                 // &lt;0 / 0 / &gt;0，与 strcmp 类似</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>C 字符串互转<a href="#c-字符串互转"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>string</span><span> </span><span>cpp_s</span><span> </span><span>=</span><span> </span><span>"hello"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>char*</span><span> </span><span>c_s</span><span> </span><span>=</span><span> </span><span>cpp_s</span><span>.</span><span>c_str</span><span>();</span><span>     // string → C 串（用于旧接口/printf）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>string</span><span> </span><span>back</span><span> </span><span>=</span><span> </span><span>c_s</span><span>;</span><span>              // C 串 → string 直接构造</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、数组 vs vector 选型<a href="#四数组-vs-vector-选型"><span>#</span></a></h2>

<table><thead><tr><th>维度</th><th>C 数组</th><th>std::vector</th></tr></thead><tbody><tr><td>大小</td><td>编译期固定</td><td>运行期动态</td></tr><tr><td>越界检查</td><td>无（UB）</td><td><code>at()</code> 有</td></tr><tr><td>自带长度</td><td>否</td><td><code>size()</code></td></tr><tr><td>传参</td><td>退化指针+手动传长度</td><td>直接传引用</td></tr><tr><td>性能</td><td>裸奔最快</td><td>同量级（多了薄封装）</td></tr></tbody></table><p><strong>结论</strong>：日常一律 vector；只有”大小确定且追求极致”（嵌入式、竞赛固定槽位）用数组。多维场景用 <code>std::vector&lt;std::vector&lt;int&gt;&gt;</code>。</p></section>
<section><h2>五、案例：成绩分析器<a href="#五案例成绩分析器"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>5</div></div><div><span>#include</span><span> </span><span>&lt;iomanip&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;std::</span><span>pair</span><span>&lt;std::</span><span>string</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>students</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>{</span><span>"小明"</span><span>, </span><span>90</span><span>}, {</span><span>"小红"</span><span>, </span><span>85</span><span>}, {</span><span>"小刚"</span><span>, </span><span>92</span><span>}, {</span><span>"小美"</span><span>, </span><span>66</span><span>},</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>// 按成绩降序</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>sort</span><span>(</span><span>students</span><span>.</span><span>begin</span><span>(), </span><span>students</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>14</div></div><div><span><span>              </span></span><span>[](</span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>b</span><span>) { </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>second</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>.</span><span>second</span><span>; });</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>// 统计</span></div></div><div><div><div>17</div></div><div><span>    </span><span>int</span><span> </span><span>total</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>scores</span><span>;</span></div></div><div><div><div>19</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>name</span><span>, </span><span>score</span><span>] : </span><span>students</span><span>) {</span><span>   // 结构化绑定（C++17）</span></div></div><div><div><div>20</div></div><div><span>        </span><span>total</span><span> </span><span>+=</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>21</div></div><div><span>        </span><span>scores</span><span>.</span><span>push_back</span><span>(</span><span>score</span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>fixed</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>setprecision</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"平均分: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>total</span><span> </span><span>*</span><span> </span><span>1.0</span><span> </span><span>/</span><span> </span><span>students</span><span>.</span><span>size</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"最高: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>scores</span><span>.</span><span>front</span><span>() </span><span>&lt;&lt;</span><span> </span><span>" 最低: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>scores</span><span>.</span><span>back</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>// 挂科名单</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"挂科: "</span><span>;</span></div></div><div><div><div>30</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>name</span><span>, </span><span>score</span><span>] : </span><span>students</span><span>)</span></div></div><div><div><div>31</div></div><div><span>        </span><span>if</span><span> (</span><span>score</span><span> </span><span>&lt;</span><span> </span><span>60</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>// 前三名</span></div></div><div><div><div>35</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>3</span><span> </span><span>&amp;&amp;</span><span> </span><span>i</span><span> </span><span>&lt;</span><span> </span><span><span>static_cast</span><span>&lt;int&gt;</span></span><span>(</span><span>students</span><span>.</span><span>size</span><span>()); </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"No."</span><span> </span><span>&lt;&lt;</span><span> </span><span>i</span><span> </span><span>+</span><span> </span><span>1</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>students</span><span>[</span><span>i</span><span>].</span><span>first</span></div></div><div><div><div>37</div></div><div><span>                  </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>students</span><span>[</span><span>i</span><span>].</span><span>second</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>38</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>不用 sort：手写选择排序把 <code>{5,2,8,1}</code> 升序（双重循环打擂台）</li>
<li>vector 去重：先排序，再 <code>std::unique</code> + <code>erase</code> 三连（查文档实现）</li>
<li>统计一句话中每个单词长度：<code>"the quick brown fox"</code> → 3 5 5 3（stringstream 分割）</li>
<li>判断回文字符串（string 下标首尾双指针）</li>
<li>二维 vector 乘法表：<code>std::vector&lt;std::vector&lt;int&gt;&gt;(9, std::vector&lt;int&gt;(9))</code> 填充并打印</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>数组大小固定、不查越界、传参退化——现代 C++ 默认 vector</li>
<li>vector：push_back 尾增 O(1)、at() 安全访问、insert/erase 中间 O(n)</li>
<li>排序查找认准 <code>&lt;algorithm&gt;</code> 的 sort/find</li>
<li>string 可下标修改、substr 切子串、find 配 <code>string::npos</code> 判断</li>
<li>分割字符串用 stringstream + getline；C 互转靠 c_str()</li>
</ul><p><strong>下一篇</strong>：指针与引用——C++ 的深水区，也是它强大的根源。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。vector 的每个方法都敲一遍，后面 STL 篇会轻松很多。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-06/</id>
      <title type="text">C++ 入门教程（六）：指针与引用</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-06/"/>
      <summary type="text">征服 C++ 深水区：内存模型与地址、指针定义解引用、指针与数组、动态内存 new/delete、悬空指针与内存泄漏、引用与指针对比、智能指针 unique_ptr/shared_ptr 入门。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>指针是 C++ 的分水岭：理解了它，才算真正理解”程序如何在内存中运行”。本篇从内存模型讲起，覆盖裸指针、动态内存、引用对比与智能指针入门。<strong>请逐个示例亲手运行</strong>——这一篇没有捷径。</p></section>
<section><h2>一、内存模型：变量住在哪里<a href="#一内存模型变量住在哪里"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>18</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这行代码发生的事：程序在<strong>栈内存</strong>里划出 4 字节，存入 18，并把这块空间标记为 <code>age</code>。</p><p>每块内存都有编号——<strong>地址</strong>（一串十六进制数）。<code>&amp;</code> 取地址运算符可以拿到它：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>&amp;</span><span>age</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // 0x7ffee4c0a8bc（每次运行可能不同）</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>sizeof</span><span>(</span><span>age</span><span>);</span><span>       // 4 字节</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>类比</strong>：内存是一整条街的房间，变量是房间里的住户，地址是门牌号。</p></section>
<section><h2>二、指针：存地址的变量<a href="#二指针存地址的变量"><span>#</span></a></h2><section><h3>定义与解引用<a href="#定义与解引用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>&amp;</span><span>age</span><span>;</span><span>          // p 是指针，存的是 age 的地址</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>     // 地址：0x7ffee4c0a8bc</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 18：* 解引用——顺着地址找到值</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>&amp;</span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // p 自己的地址（指针也是变量）</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>*</span><span>p</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span><span>                    // 通过地址改写 age！</span></div></div><div><div><div>9</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>age</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 20</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>两个符号记牢</strong>：</p><ul>
<li><code>&amp;x</code>：取 x 的<strong>地址</strong></li>
<li><code>*p</code>：顺 p 存的地址<strong>取值</strong>（或写入）</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int*</span><span> </span><span>p1</span><span>, </span><span>p2</span><span>;</span><span>        // ⚠ 坑：p1 是指针，p2 是 int！</span></div></div><div><div><div>2</div></div><div><span>int</span><span> </span><span>*</span><span>p3</span><span>, </span><span>*</span><span>p4</span><span>;</span><span>       // 两个都是指针</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>空指针与安全<a href="#空指针与安全"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>nullptr</span><span>;</span><span>       // C++11 空指针（替代 NULL 与 0）</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span> (</span><span>p</span><span> </span><span>!=</span><span> </span><span>nullptr</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>p</span><span>;</span><span>    // 用前判空</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>// *p;                  // ❌ 解引用空指针 = 段错误（Segfault），程序崩溃</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>永远不要解引用空指针或未初始化的指针（野指针）。现代写法：定义指针就初始化（给值或给 nullptr）。</p></div></div></section><section><h3>指针作为函数参数<a href="#指针作为函数参数"><span>#</span></a></h3><p>C 风格的”修改实参”方式（C++ 更推荐引用，但必须会读）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>swap</span><span>(</span><span>int*</span><span><span> </span><span>a</span><span>, </span></span><span>int*</span><span><span> </span><span>b</span><span>) {</span></span><span>      // 接收地址</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> </span><span>t</span><span> </span><span>=</span><span> </span><span>*</span><span>a</span><span>;</span><span>                  // 通过地址取值</span></div></div><div><div><div>3</div></div><div><span>    </span><span>*</span><span>a</span><span> </span><span>=</span><span> </span><span>*</span><span>b</span><span>;</span><span>                     // 通过地址写值</span></div></div><div><div><div>4</div></div><div><span>    </span><span>*</span><span>b</span><span> </span><span>=</span><span> </span><span>t</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>int</span><span> </span><span>x</span><span> </span><span>=</span><span> </span><span>1</span><span>, </span><span>y</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>swap</span><span>(</span><span>&amp;</span><span>x</span><span>, </span><span>&amp;</span><span>y</span><span>);</span><span>                // 传地址</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>x</span><span> </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>y</span><span>;</span><span>  // 2,1</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>指针与数组<a href="#指针与数组"><span>#</span></a></h3><p>数组名本质是”首元素地址”：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>arr</span><span>[] </span><span>=</span><span> {</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>};</span></div></div><div><div><div>2</div></div><div><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>arr</span><span>;</span><span>                    // 等价于 &amp;arr[0]</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>         // 10</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>(</span><span>p</span><span> </span><span>+</span><span> </span><span>1</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 20：指针算术，+1 移动一个 int</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>p</span><span>[</span><span>2</span><span>] </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // 30：指针也能用下标（等价 *(p+2)）</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 遍历</span></div></div><div><div><div>9</div></div><div><span>for</span><span> (</span><span>int*</span><span> </span><span>q</span><span> </span><span>=</span><span> </span><span>arr</span><span>; </span><span>q</span><span> </span><span>!=</span><span> </span><span>arr</span><span> </span><span>+</span><span> </span><span>4</span><span>; </span><span>++</span><span>q</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>q</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>指针算术</strong>：<code>p + 1</code> 移动的字节数 = 指向类型的大小（int* 移 4 字节，double* 移 8 字节）。</p></section></section>
<section><h2>三、动态内存：new / delete<a href="#三动态内存new--delete"><span>#</span></a></h2><p>栈上的变量函数结束自动销毁；<strong>堆内存</strong>由你手动管理——能跨函数存活、大小运行期决定。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 单个变量</span></div></div><div><div><div>2</div></div><div><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>(</span><span>42</span><span>);</span><span>            // 堆上开 4 字节，初始化 42</span></div></div><div><div><div>3</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>delete</span><span> </span><span>p</span><span>;</span><span>                        // 手动释放！</span></div></div><div><div><div>5</div></div><div><span>p</span><span> </span><span>=</span><span> </span><span>nullptr</span><span>;</span><span>                     // 置空好习惯</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 动态数组（大小可以是变量！）</span></div></div><div><div><div>8</div></div><div><span>int</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>9</div></div><div><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>10</div></div><div><span>int*</span><span> </span><span>arr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>[</span><span>n</span><span>]{};</span><span>         // n 个 int 全 0</span></div></div><div><div><div>11</div></div><div><span>for</span><span> (</span><span>int</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>n</span><span>; </span><span>++</span><span>i</span><span>) </span><span>arr</span><span>[</span><span>i</span><span>] </span><span>=</span><span> </span><span>i</span><span> </span><span>*</span><span> </span><span>i</span><span>;</span></div></div><div><div><div>12</div></div><div><span>delete[]</span><span> </span><span>arr</span><span>;</span><span>                    // 数组用 delete[]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>两条铁律</strong>：</p><ol>
<li>每个 <code>new</code> 必须对应一个 <code>delete</code>（数组 <code>delete[]</code>）</li>
<li><code>delete</code> 后指针置 <code>nullptr</code>，防止”悬空指针”再次使用</li>
</ol><section><h3>内存泄漏：忘记 delete<a href="#内存泄漏忘记-delete"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>leak</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>(</span><span>100</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>// 函数结束，p 这个"门牌号"没了，但堆上 4 字节还占着——永远无法释放</span></div></div><div><div><div>4</div></div><div><span>}</span><span>   // 💥 内存泄漏</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>void</span><span> </span><span>worse</span><span>() {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>(</span><span>2</span><span>);</span><span>              // 第一个内存块地址丢失，泄漏！</span></div></div><div><div><div>9</div></div><div><span>    </span><span>delete</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>长期运行的服务（服务器程序）泄漏累积会耗尽内存——这是裸 new/delete 逐渐被弃用的原因。</p></section></section>
<section><h2>四、引用 vs 指针<a href="#四引用-vs-指针"><span>#</span></a></h2>

<table><thead><tr><th>维度</th><th>引用 <code>int&amp; r = x</code></th><th>指针 <code>int* p = &amp;x</code></th></tr></thead><tbody><tr><td>本质</td><td>变量的别名</td><td>存地址的变量</td></tr><tr><td>初始化</td><td><strong>必须</strong>初始化，不可换绑</td><td>可空、可改指向</td></tr><tr><td>空值</td><td>不存在</td><td>nullptr</td></tr><tr><td>用法</td><td>直接当原变量用</td><td>需 <code>*</code> 解引用</td></tr><tr><td>安全性</td><td>高</td><td>低（野指针/泄漏）</td></tr></tbody></table><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>x</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>int</span><span>&amp;</span></span><span> </span><span>r</span><span> </span><span>=</span><span> </span><span>x</span><span>;</span><span>          // r 就是 x 的第二个名字</span></div></div><div><div><div>4</div></div><div><span>r</span><span> </span><span>=</span><span> </span><span>99</span><span>;</span><span>              // x 变 99</span></div></div><div><div><div>5</div></div><div><span>// int&amp; bad;         // ❌ 引用必须初始化</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>&amp;</span><span>x</span><span>;</span><span>         // p 指向 x</span></div></div><div><div><div>8</div></div><div><span>p</span><span> </span><span>=</span><span> </span><span>nullptr</span><span>;</span><span>         // ✓ 指针可以为空</span></div></div><div><div><div>9</div></div><div><span>int</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>10</div></div><div><span>p</span><span> </span><span>=</span><span> </span><span>&amp;</span><span>y</span><span>;</span><span>              // ✓ 指针可换指向</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>选择</strong>：能用引用就用引用（安全简洁）；需要”可能为空”或”改指向”才用指针。</p></section>
<section><h2>五、智能指针（现代 C++ 的答案）<a href="#五智能指针现代-c-的答案"><span>#</span></a></h2><p>C++11 用智能指针把 new/delete 交给对象自动管理——<strong>RAII</strong>：资源获取即初始化，析构自动释放。</p><section><h3>unique_ptr：独占所有权<a href="#unique_ptr独占所有权"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;memory&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>// make_unique 创建（C++14）</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>unique_ptr</span><span>&lt;</span><span>int</span><span>&gt; </span><span>p</span><span> </span><span>=</span><span> std::</span><span>make_unique</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>42</span><span>);</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>p</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>     // 像普通指针一样用</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>// 离开作用域自动 delete，无需也无法手动 delete</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>// auto q = p;               // ❌ unique 不可拷贝（独占）</span></div></div><div><div><div>12</div></div><div><span>    </span><span>auto</span><span> </span><span>q</span><span> </span><span>=</span><span> std::</span><span>move</span><span>(</span><span>p</span><span>);</span><span>       // ✓ 只能转移所有权（p 变空）</span></div></div><div><div><div>13</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span>p</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"p 已交出</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>q</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span><span>   // q 析构 → 自动释放内存</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>shared_ptr：共享所有权（计数引用）<a href="#shared_ptr共享所有权计数引用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;memory&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>auto</span><span> </span><span>a</span><span> </span><span>=</span><span> std::</span><span>make_shared</span><span>&lt;</span><span>int</span><span>&gt;(</span><span>100</span><span>);</span><span>   // 引用计数 = 1</span></div></div><div><div><div>4</div></div><div><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>auto</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>a</span><span>;</span><span>                        // 计数 = 2，可以拷贝</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span><span>                                      // b 销毁，计数 = 1</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span>.</span><span>use_count</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 1</span></div></div><div><div><div>9</div></div><div><span>// a 销毁时计数归零 → 内存自动释放</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>选型</strong>：默认 unique_ptr；确实多方持有才 shared_ptr。</p></section></section>
<section><h2>六、实战：链表节点（指针的第一次真实应用）<a href="#六实战链表节点指针的第一次真实应用"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>struct</span><span> </span><span>Node</span><span> {</span><span>              // 结构体第八篇详讲，先看用法</span></div></div><div><div><div>4</div></div><div><span>    </span><span>int</span><span> </span><span>data</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Node</span><span>*</span><span> </span><span>next</span><span>;</span><span>            // 指向下一个节点——链表的骨架</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>// 用 new 造三个节点</span></div></div><div><div><div>10</div></div><div><span>    </span><span>Node</span><span>*</span><span> </span><span>head</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Node</span><span>{</span><span>1</span><span>, </span><span>nullptr</span><span>};</span></div></div><div><div><div>11</div></div><div><span>    </span><span>head</span><span>-&gt;</span><span>next</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Node</span><span>{</span><span>2</span><span>, </span><span>nullptr</span><span>};</span><span>      // -&gt; 通过指针访问成员</span></div></div><div><div><div>12</div></div><div><span>    </span><span>head</span><span>-&gt;</span><span>next</span><span>-&gt;</span><span>next</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Node</span><span>{</span><span>3</span><span>, </span><span>nullptr</span><span>};</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>// 遍历</span></div></div><div><div><div>15</div></div><div><span>    </span><span>for</span><span> (</span><span>Node</span><span>*</span><span> </span><span>cur</span><span> </span><span>=</span><span> </span><span>head</span><span>; </span><span>cur</span><span> </span><span>!=</span><span> </span><span>nullptr</span><span>; </span><span>cur</span><span> </span><span>=</span><span> </span><span>cur</span><span>-&gt;</span><span>next</span><span>)</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>cur</span><span>-&gt;</span><span>data</span><span> </span><span>&lt;&lt;</span><span> </span><span>" -&gt; "</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"null</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>// 逐个释放（防泄漏）</span></div></div><div><div><div>20</div></div><div><span>    </span><span>Node</span><span>*</span><span> </span><span>cur</span><span> </span><span>=</span><span> </span><span>head</span><span>;</span></div></div><div><div><div>21</div></div><div><span>    </span><span>while</span><span> (</span><span>cur</span><span> </span><span>!=</span><span> </span><span>nullptr</span><span>) {</span></div></div><div><div><div>22</div></div><div><span>        </span><span>Node</span><span>*</span><span> </span><span>next</span><span> </span><span>=</span><span> </span><span>cur</span><span>-&gt;</span><span>next</span><span>;</span><span>    // 先记住下一个</span></div></div><div><div><div>23</div></div><div><span>        </span><span>delete</span><span> </span><span>cur</span><span>;</span><span>                // 再释放当前</span></div></div><div><div><div>24</div></div><div><span>        </span><span>cur</span><span> </span><span>=</span><span> </span><span>next</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这个例子同时展示了：堆分配、<code>-&gt;</code> 运算符、指针串联结构、手动释放顺序。以后用 <code>std::unique_ptr&lt;Node&gt; next</code> 重写它，就是现代 C++ 风格。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写 <code>int* find_max(int* arr, int n)</code> 返回最大元素的<strong>地址</strong>（不是值）</li>
<li>用 new 申请一个 <code>double</code> 数组存 10 个成绩，输出平均分后正确 delete</li>
<li>验证”值传递不改原值、指针与引用传递改原值”：同一功能写三个版本对比</li>
<li>用 unique_ptr 管理一个动态 int 数组（<code>std::unique_ptr&lt;int[]&gt; arr{new int[5]{}}</code>），体会自动释放</li>
<li>（概念题）<code>int* p = new int(5); delete p; std::cout &lt;&lt; *p;</code> 会发生什么？（悬空指针，未定义行为——说说为什么不能这么写）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li><code>&amp;</code> 取地址、<code>*p</code> 解引用；指针存地址，是”携带门牌号的变量”</li>
<li>数组名≈首元素地址，指针算术按类型大小移动</li>
<li>new/delete 手动管理堆：一一配对、delete 后置空、防泄漏</li>
<li>引用是必须初始化的别名，优先用引用；可为空/换指向才用指针</li>
<li>现代 C++ 用 unique_ptr/shared_ptr 自动管理内存（RAII）</li>
<li><code>-&gt;</code> 是”指针访问成员”的语法糖</li>
</ul><p><strong>下一篇</strong>：结构体与枚举——把相关数据打包成自定义类型。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。指针是 C++ 的门槛也是魅力：内存模型想通了，后面豁然开朗。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-07/</id>
      <title type="text">C++ 入门教程（七）：结构体与枚举</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-07/"/>
      <summary type="text">掌握 struct 定义与使用、成员访问与嵌套、结构体数组与 vector、结构体作函数参数、enum 与 enum class 的区别、联合体简介，用学生管理与坐标系统案例练手。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>int/double/string 只能描述”单点信息”，现实实体往往是”一组信息”：学生有姓名+年龄+成绩，坐标有 x+y。<strong>结构体（struct）</strong> 让你自定义”打包类型”；<strong>枚举（enum）</strong> 让你定义”取值受限”的类型。它们是迈向面向对象（第九篇）前的最后一级台阶。</p></section>
<section><h2>一、结构体基础<a href="#一结构体基础"><span>#</span></a></h2><section><h3>定义与使用<a href="#定义与使用"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 定义新类型（习惯放 main 前或头文件）</span></div></div><div><div><div>5</div></div><div><span>struct</span><span> </span><span>Student</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name</span><span>;</span><span>     // 成员变量</span></div></div><div><div><div>7</div></div><div><span>    </span><span>int</span><span> </span><span>age</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>double</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>9</div></div><div><span>};</span><span>                        // ⚠ 别忘了分号！</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>// 创建与初始化（三种方式）</span></div></div><div><div><div>13</div></div><div><span>    </span><span>Student</span><span> </span><span>s1</span><span> </span><span>=</span><span> {</span><span>"小明"</span><span>, </span><span>18</span><span>, </span><span>90.5</span><span>};</span><span>          // 顺序初始化</span></div></div><div><div><div>14</div></div><div><span>    </span><span>Student</span><span> </span><span>s2</span><span>{.</span><span>name</span><span>=</span><span>"小红"</span><span>, .</span><span>age</span><span>=</span><span>17</span><span>};</span><span>        // 指示符初始化（C++20）</span></div></div><div><div><div>15</div></div><div><span>    </span><span>Student</span><span> </span><span>s3</span><span>;</span><span>                               // 未初始化（成员值随机！）</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>// 成员访问：点运算符</span></div></div><div><div><div>18</div></div><div><span>    </span><span>s3</span><span>.</span><span>name</span><span> </span><span>=</span><span> </span><span>"小刚"</span><span>;</span></div></div><div><div><div>19</div></div><div><span>    </span><span>s3</span><span>.</span><span>age</span><span> </span><span>=</span><span> </span><span>19</span><span>;</span></div></div><div><div><div>20</div></div><div><span>    </span><span>s3</span><span>.</span><span>score</span><span> </span><span>=</span><span> </span><span>88</span><span>;</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s1</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>s1</span><span>.</span><span>score</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s2</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>s2</span><span>.</span><span>score</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 0（缺省补零）</span></div></div><div><div><div>24</div></div><div><span>    </span><span>return</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>指针访问成员：-&gt;<a href="#指针访问成员-"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Student</span><span> </span><span>s</span><span> </span><span>=</span><span> {</span><span>"小明"</span><span>, </span><span>18</span><span>, </span><span>90.5</span><span>};</span></div></div><div><div><div>2</div></div><div><span>Student</span><span>*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>&amp;</span><span>s</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>*</span><span>p</span><span>).</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 括号版（* 优先级低于 .）</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>p</span><span>-&gt;</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // 箭头版（完全等价，推荐）</span></div></div><div><div><div>6</div></div><div><span>p</span><span>-&gt;</span><span>score</span><span> </span><span>=</span><span> </span><span>95</span><span>;</span><span>                     // 通过指针修改成员</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>规则</strong>：对象/引用用 <code>.</code>，指针用 <code>-&gt;</code>。</p></section><section><h3>结构体嵌套<a href="#结构体嵌套"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>struct</span><span> </span><span>Date</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> </span><span>year</span><span>, </span><span>month</span><span>, </span><span>day</span><span>;</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>struct</span><span> </span><span>Event</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>title</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Date</span><span> </span><span>date</span><span>;</span><span>              // 结构体作成员</span></div></div><div><div><div>8</div></div><div><span>    </span><span>struct</span><span> </span><span>Place</span><span> {</span><span>          // 内嵌定义</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>std::</span><span>string</span><span> </span><span>building</span><span>;</span></div></div><div><div><div>10</div></div><div><span>        </span><span>int</span><span> </span><span>room</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>} </span><span>place</span><span>;</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>Event</span><span> </span><span>e</span><span>;</span></div></div><div><div><div>15</div></div><div><span>e</span><span>.</span><span>title</span><span> </span><span>=</span><span> </span><span>"C++ 分享会"</span><span>;</span></div></div><div><div><div>16</div></div><div><span>e</span><span>.</span><span>date</span><span> </span><span>=</span><span> {</span><span>2026</span><span>, </span><span>10</span><span>, </span><span>29</span><span>};</span></div></div><div><div><div>17</div></div><div><span>e</span><span>.</span><span>place</span><span>.</span><span>building</span><span> </span><span>=</span><span> </span><span>"信息楼"</span><span>;</span></div></div><div><div><div>18</div></div><div><span>e</span><span>.</span><span>place</span><span>.</span><span>room</span><span> </span><span>=</span><span> </span><span>301</span><span>;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>title</span><span> </span><span>&lt;&lt;</span><span> </span><span>" @ "</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>place</span><span>.</span><span>building</span></div></div><div><div><div>21</div></div><div><span>          </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>place</span><span>.</span><span>room</span><span> </span><span>&lt;&lt;</span><span> </span><span>"室</span><span>\n</span><span>"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>二、结构体与容器/函数<a href="#二结构体与容器函数"><span>#</span></a></h2><section><h3>结构体数组与 vector<a href="#结构体数组与-vector"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>Student</span><span>&gt;</span><span> </span><span>students</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>{</span><span>"小明"</span><span>, </span><span>18</span><span>, </span><span>90</span><span>}, {</span><span>"小红"</span><span>, </span><span>17</span><span>, </span><span>85</span><span>}, {</span><span>"小刚"</span><span>, </span><span>19</span><span>, </span><span>92</span><span>},</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 遍历</span></div></div><div><div><div>9</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>s</span><span> : </span><span>students</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>score</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 按分数降序（结构化绑定 + lambda）</span></div></div><div><div><div>13</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>students</span><span>.</span><span>begin</span><span>(), </span><span>students</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>14</div></div><div><span><span>          </span></span><span>[](</span><span>const</span><span> </span><span>Student</span><span>&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>Student</span><span>&amp;</span><span><span> </span><span>b</span><span>) { </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>score</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>.</span><span>score</span><span>; });</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// 找最高分</span></div></div><div><div><div>17</div></div><div><span>auto</span><span> </span><span>best</span><span> </span><span>=</span><span> </span><span>*</span><span><span>std</span><span>::</span></span><span>max_element</span><span>(</span><span>students</span><span>.</span><span>begin</span><span>(), </span><span>students</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>18</div></div><div><span><span>          </span></span><span>[](</span><span>const</span><span> </span><span>Student</span><span>&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>Student</span><span>&amp;</span><span><span> </span><span>b</span><span>) { </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>score</span><span> </span><span>&lt;</span><span> </span><span>b</span><span>.</span><span>score</span><span>; });</span></div></div><div><div><div>19</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"第一名: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>best</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>作函数参数：const 引用优先<a href="#作函数参数const-引用优先"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 大结构体只读：const&amp; 零拷贝</span></div></div><div><div><div>2</div></div><div><span>void</span><span> </span><span>print_student</span><span>(</span><span>const</span><span> </span><span>Student</span><span>&amp;</span><span><span> </span><span>s</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>age</span><span> </span><span>&lt;&lt;</span><span> </span><span>"岁,"</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>score</span><span> </span><span>&lt;&lt;</span><span> </span><span>"分</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 要修改：引用</span></div></div><div><div><div>7</div></div><div><span>void</span><span> </span><span>birthday</span><span>(</span><span>Student</span><span>&amp;</span><span><span> </span><span>s</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>++</span><span>s</span><span>.</span><span>age</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 值传递会整体拷贝（string/vector 都复制一遍）——大结构体别这么传</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>运算符重载初见（让结构体支持比较/输出）<a href="#运算符重载初见让结构体支持比较输出"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>struct</span><span> </span><span>Point</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>double</span><span> </span><span>x</span><span>, </span><span>y</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>// 成员函数（第九篇正式讲）</span></div></div><div><div><div>5</div></div><div><span>    </span><span>double</span><span> </span><span>dist</span><span>() </span><span>const</span><span> { </span><span>return</span><span> std::</span><span>sqrt</span><span>(</span><span>x</span><span>*</span><span>x</span><span> </span><span>+</span><span> </span><span>y</span><span>*</span><span>y</span><span>); }</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>完整的运算符重载（<code>operator&lt;</code>、<code>operator==</code>）在第十篇面向对象展开。</p></section></section>
<section><h2>三、枚举<a href="#三枚举"><span>#</span></a></h2><section><h3>传统 enum（无作用域，有坑）<a href="#传统-enum无作用域有坑"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>Color</span><span> { </span><span>RED</span><span>, </span><span>GREEN</span><span>, </span><span>BLUE</span><span> };</span><span>        // 默认值 0,1,2</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>Color</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>GREEN</span><span>;</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>                 // 1（本质是 int）</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>if</span><span> (</span><span>c</span><span> </span><span>==</span><span> </span><span>GREEN</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"绿色</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>enum</span><span> </span><span>Level</span><span> { </span><span>LOW</span><span>, </span><span>MID</span><span> </span><span>=</span><span> </span><span>5</span><span>, </span><span>HIGH</span><span> };</span><span>      // 可指定值：0,5,6</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>坑：枚举名<strong>裸露在全局</strong>，两个 enum 有同名成员就冲突：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>TrafficLight</span><span> { </span><span>RED</span><span>, </span><span>YELLOW</span><span>, </span><span>GREEN</span><span> };</span><span>   // ❌ RED/GREEN 与 Color 重复定义！</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>enum class（C++11，强类型枚举——现代首选）<a href="#enum-classc11强类型枚举现代首选"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>class</span><span> </span><span>Status</span><span> { </span><span>Idle</span><span>, </span><span>Running</span><span>, </span><span>Error</span><span> };</span></div></div><div><div><div>2</div></div><div><span>enum</span><span> </span><span>class</span><span> </span><span>Color2</span><span> { </span><span>Red</span><span>, </span><span>Green</span><span> };</span><span>          // 同名不冲突：有作用域</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>Status</span><span> </span><span>s</span><span> </span><span>=</span><span> Status::</span><span>Running</span><span>;</span><span>                 // 必须带作用域 Status::</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>if</span><span> (</span><span>s</span><span> </span><span>==</span><span> Status::</span><span>Running</span><span>)</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"运行中</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// int n = s;               // ❌ 不隐式转 int（类型安全）</span></div></div><div><div><div>10</div></div><div><span>int</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span><span>static_cast</span><span>&lt;int&gt;</span></span><span>(</span><span>s</span><span>);</span><span> // 显式转换 ✓</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 指定底层类型</span></div></div><div><div><div>13</div></div><div><span>enum</span><span> </span><span>class</span><span> </span><span>Priority</span><span> : </span><span>char</span><span> { </span><span>Low</span><span> </span><span>=</span><span> </span><span>'L'</span><span>, </span><span>Mid</span><span> </span><span>=</span><span> </span><span>'M'</span><span>, </span><span>High</span><span> </span><span>=</span><span> </span><span>'H'</span><span> };</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>enum class 三大优点</strong>：作用域隔离（不污染全局）、不隐式转 int（防误比较）、可指定底层类型。<strong>新代码一律 enum class</strong>。</p></section><section><h3>枚举 + switch：状态机标配<a href="#枚举--switch状态机标配"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enum</span><span> </span><span>class</span><span> </span><span>OrderState</span><span> { </span><span>Created</span><span>, </span><span>Paid</span><span>, </span><span>Shipped</span><span>, </span><span>Done</span><span>, </span><span>Cancelled</span><span> };</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>void</span><span> </span><span>handle</span><span>(</span><span>OrderState</span><span><span> </span><span>state</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>switch</span><span> (</span><span>state</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>case</span><span> OrderState::</span><span>Created</span><span>:  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"待支付</span><span>\n</span><span>"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>6</div></div><div><span>        </span><span>case</span><span> OrderState::</span><span>Paid</span><span>:     std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"已支付，备货中</span><span>\n</span><span>"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>7</div></div><div><span>        </span><span>case</span><span> OrderState::</span><span>Shipped</span><span>:  std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"运输中</span><span>\n</span><span>"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>8</div></div><div><span>        </span><span>case</span><span> OrderState::</span><span>Done</span><span>:     std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"已完成</span><span>\n</span><span>"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>9</div></div><div><span>        </span><span>case</span><span> OrderState::</span><span>Cancelled</span><span>:std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"已取消</span><span>\n</span><span>"</span><span>; </span><span>break</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>// ⚠ 开了 -Wall 编译选项时，漏分支会警告——enum+switch 的安全网</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、联合体与位域（了解）<a href="#四联合体与位域了解"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// union：所有成员共享同一块内存（省空间，底层开发用）</span></div></div><div><div><div>2</div></div><div><span>union</span><span> </span><span>Packet</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>uint32_t</span><span> </span><span>raw</span><span>;</span><span>                 // 4 字节</span></div></div><div><div><div>4</div></div><div><span>    </span><span>struct</span><span> { </span><span>uint8_t</span><span> </span><span>b0</span><span>,</span><span>b1</span><span>,</span><span>b2</span><span>,</span><span>b3</span><span>; } </span><span>bytes</span><span>;</span><span>   // 也是 4 字节，与 raw 重叠</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>Packet</span><span> </span><span>p</span><span>;</span></div></div><div><div><div>8</div></div><div><span>p</span><span>.</span><span>raw</span><span> </span><span>=</span><span> </span><span><span>0x</span><span>11223344</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>hex</span><span> </span><span>&lt;&lt;</span><span> (</span><span>int</span><span>)</span><span>p</span><span>.</span><span>bytes</span><span>.</span><span>b0</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 44（小端序）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>应用场景：硬件寄存器、网络协议解析。日常业务开发用得少，知道即可。</p></section>
<section><h2>五、综合案例：图书管理（结构体版）<a href="#五综合案例图书管理结构体版"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>5</div></div><div><span>#include</span><span> </span><span>&lt;iomanip&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>enum</span><span> </span><span>class</span><span> </span><span>BookState</span><span> { </span><span>Available</span><span>, </span><span>Borrowed</span><span>, </span><span>Lost</span><span> };</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>struct</span><span> </span><span>Book</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>isbn</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>title</span><span>;</span></div></div><div><div><div>12</div></div><div><span>    </span><span>BookState</span><span> </span><span>state</span><span>;</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>state_str</span><span>() </span><span>const</span><span> {</span><span>           // const 成员函数</span></div></div><div><div><div>15</div></div><div><span>        </span><span>switch</span><span> (</span><span>state</span><span>) {</span></div></div><div><div><div>16</div></div><div><span>            </span><span>case</span><span> BookState::</span><span>Available</span><span>: </span><span>return</span><span> </span><span>"在架"</span><span>;</span></div></div><div><div><div>17</div></div><div><span>            </span><span>case</span><span> BookState::</span><span>Borrowed</span><span>:  </span><span>return</span><span> </span><span>"借出"</span><span>;</span></div></div><div><div><div>18</div></div><div><span>            </span><span>case</span><span> BookState::</span><span>Lost</span><span>:      </span><span>return</span><span> </span><span>"遗失"</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>        </span><span>return</span><span> </span><span>"?"</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>};</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>struct</span><span> </span><span>Library</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>Book</span><span>&gt; </span><span>books</span><span>;</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>    </span><span>void</span><span> </span><span>add</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>isbn</span><span>, </span></span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>title</span><span>) {</span></span></div></div><div><div><div>28</div></div><div><span>        </span><span>books</span><span>.</span><span>push_back</span><span>({</span><span>isbn</span><span>, </span><span>title</span><span>, BookState::</span><span>Available</span><span>});</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>    </span><span>bool</span><span> </span><span>borrow</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>isbn</span><span>) {</span></span></div></div><div><div><div>32</div></div><div><span>        </span><span>for</span><span> (</span><span>auto&amp;</span><span> </span><span>b</span><span> : </span><span>books</span><span>)</span></div></div><div><div><div>33</div></div><div><span>            </span><span>if</span><span> (</span><span>b</span><span>.</span><span>isbn</span><span> </span><span>==</span><span> </span><span>isbn</span><span> </span><span>&amp;&amp;</span><span> </span><span>b</span><span>.</span><span>state</span><span> </span><span>==</span><span> BookState::</span><span>Available</span><span>) {</span></div></div><div><div><div>34</div></div><div><span>                </span><span>b</span><span>.</span><span>state</span><span> </span><span>=</span><span> BookState::</span><span>Borrowed</span><span>;</span></div></div><div><div><div>35</div></div><div><span>                </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>36</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span>        </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>    </span><span>void</span><span> </span><span>report</span><span>() </span><span>const</span><span> {</span></div></div><div><div><div>41</div></div><div><span>        </span><span>int</span><span> </span><span>avail</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>42</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>b</span><span> : </span><span>books</span><span>)</span></div></div><div><div><div>43</div></div><div><span>            </span><span>if</span><span> (</span><span>b</span><span>.</span><span>state</span><span> </span><span>==</span><span> BookState::</span><span>Available</span><span>) </span><span>++</span><span>avail</span><span>;</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"共 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>books</span><span>.</span><span>size</span><span>() </span><span>&lt;&lt;</span><span> </span><span>" 本，在架 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>avail</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 本</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>45</div></div><div>
</div></div><div><div><div>46</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>b</span><span> : </span><span>books</span><span>)</span></div></div><div><div><div>47</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>left</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>setw</span><span>(</span><span>14</span><span>) </span><span>&lt;&lt;</span><span> </span><span>b</span><span>.</span><span>isbn</span></div></div><div><div><div>48</div></div><div><span>                      </span><span>&lt;&lt;</span><span> std::</span><span>setw</span><span>(</span><span>16</span><span>) </span><span>&lt;&lt;</span><span> </span><span>b</span><span>.</span><span>title</span></div></div><div><div><div>49</div></div><div><span>                      </span><span>&lt;&lt;</span><span> </span><span>b</span><span>.</span><span>state_str</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>50</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>51</div></div><div><span>};</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>54</div></div><div><span>    </span><span>Library</span><span> </span><span>lib</span><span>;</span></div></div><div><div><div>55</div></div><div><span>    </span><span>lib</span><span>.</span><span>add</span><span>(</span><span>"978-7-111"</span><span>, </span><span>"C++ Primer"</span><span>);</span></div></div><div><div><div>56</div></div><div><span>    </span><span>lib</span><span>.</span><span>add</span><span>(</span><span>"978-7-115"</span><span>, </span><span>"算法导论"</span><span>);</span></div></div><div><div><div>57</div></div><div><span>    </span><span>lib</span><span>.</span><span>add</span><span>(</span><span>"978-7-121"</span><span>, </span><span>"深入理解计算机系统"</span><span>);</span></div></div><div><div><div>58</div></div><div>
</div></div><div><div><div>59</div></div><div><span>    </span><span>lib</span><span>.</span><span>borrow</span><span>(</span><span>"978-7-111"</span><span>);</span></div></div><div><div><div>60</div></div><div><span>    </span><span>lib</span><span>.</span><span>borrow</span><span>(</span><span>"不存在的ISBN"</span><span>);</span></div></div><div><div><div>61</div></div><div><span>    </span><span>lib</span><span>.</span><span>report</span><span>();</span></div></div><div><div><div>62</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这个案例在第十篇会用 class + 封装重写，对比着看能体会 struct→class 的演进。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>定义 <code>Rectangle{width, height}</code> + 函数 <code>double area(const Rectangle&amp;)</code>，输入尺寸输出面积周长</li>
<li>定义 <code>Student{name, scores: vector&lt;double&gt;}</code>，写函数计算每人平均分并输出最高的姓名</li>
<li>用 enum class 表示”星期”写函数：输入 1-7 返回中文星期名（switch）</li>
<li>结构体数组按多级排序：先按年龄升序，同龄按分数降序（lambda 组合比较）</li>
<li>定义 <code>Vec2{x,y}</code> 并写 <code>add/sub/dot</code> 三个函数（const 引用传参），实现向量加减与点积</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>struct 把相关数据打包成自定义类型；定义后别忘分号</li>
<li>对象用 <code>.</code>、指针用 <code>-&gt;</code> 访问成员；结构体可嵌套</li>
<li>结构体传参：只读 <code>const&amp;</code>、要改 <code>&amp;</code>；配 vector/sort 食用最佳</li>
<li>枚举新代码用 enum class：作用域安全、不隐式转 int</li>
<li>union 了解即可；struct 是 class 的”公开版”，面向对象见第九篇</li>
</ul><p><strong>下一篇</strong>：面向对象（上）——类、构造析构、封装。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。图书管理案例先自己扩展”还书”功能，第十篇再见证它的进化。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-08/</id>
      <title type="text">C++ 入门教程（八）：面向对象（上）——类与封装</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-08/"/>
      <summary type="text">深入 C++ 类：class 与 struct 的区别、访问控制 public/private/protected、构造函数与初始化列表、析构函数、拷贝构造与拷贝赋值、深浅拷贝问题、static 成员与 this 指针。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>C++ 是”多范式语言”，但<strong>面向对象（OOP）</strong> 是它组织大型工程的主力方式。本篇讲 OOP 三大特性中的<strong>封装</strong>：把数据与操作绑定、对外隐藏细节。构造/析构/拷贝这”三巨头”是 C++ 面试与实战的高频考点。</p></section>
<section><h2>一、从 struct 到 class<a href="#一从-struct-到-class"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>BankAccount</span><span> {</span></div></div><div><div><div>2</div></div><div><span>private:</span><span>                 // 私有：只有类自己的成员函数能访问</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>owner</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>double</span><span> </span><span>balance</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>public:</span><span>                  // 公开：外部的接口</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>// 构造函数</span></div></div><div><div><div>8</div></div><div><span>    </span><span>BankAccount</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>, </span></span><span>double</span><span><span> </span><span>init_balance</span><span> </span></span><span>=</span><span> </span><span>0</span><span>)</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>: </span><span>owner</span><span>(</span><span>name</span><span>), </span><span>balance</span><span>(</span><span>init_balance</span><span>) {</span><span>    // 初始化列表</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>// 成员函数（方法）</span></div></div><div><div><div>13</div></div><div><span>    </span><span>void</span><span> </span><span>deposit</span><span>(</span><span>double</span><span><span> </span><span>amount</span><span>) {</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>if</span><span> (</span><span>amount</span><span> </span><span>&lt;=</span><span> </span><span>0</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>15</div></div><div><span>        </span><span>balance</span><span> </span><span>+=</span><span> </span><span>amount</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>bool</span><span> </span><span>withdraw</span><span>(</span><span>double</span><span><span> </span><span>amount</span><span>) {</span></span></div></div><div><div><div>19</div></div><div><span>        </span><span>if</span><span> (</span><span>amount</span><span> </span><span>&gt;</span><span> </span><span>balance</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>20</div></div><div><span>        </span><span>balance</span><span> </span><span>-=</span><span> </span><span>amount</span><span>;</span></div></div><div><div><div>21</div></div><div><span>        </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>    </span><span>double</span><span> </span><span>get_balance</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>balance</span><span>; }</span><span>   // const：承诺不修改成员</span></div></div><div><div><div>25</div></div><div><span>};</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>28</div></div><div><span>    </span><span>BankAccount</span><span> </span><span>acc</span><span>(</span><span>"小明"</span><span>, </span><span>100</span><span>);</span></div></div><div><div><div>29</div></div><div><span>    </span><span>acc</span><span>.</span><span>deposit</span><span>(</span><span>50</span><span>);</span></div></div><div><div><div>30</div></div><div><span>    </span><span>acc</span><span>.</span><span>withdraw</span><span>(</span><span>30</span><span>);</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>acc</span><span>.</span><span>get_balance</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 120</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>// acc.balance = -999;      // ❌ private，外部禁止直接改——封装的意义！</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>class 与 struct 的唯一区别</strong>：默认访问权限——class 默认 private，struct 默认 public。习惯：纯数据用 struct，带行为用 class。</p><p><strong>封装的价值</strong>：<code>balance</code> 不能被外部直接改成负数——所有修改必须经过 <code>deposit/withdraw</code> 的校验，不变量（余额非负）由类自己守护。</p></section>
<section><h2>二、访问控制三档<a href="#二访问控制三档"><span>#</span></a></h2>

<table><thead><tr><th>关键字</th><th>谁能访问</th></tr></thead><tbody><tr><td><code>private</code></td><td>本类的成员函数（默认）</td></tr><tr><td><code>protected</code></td><td>本类 + 子类（第九篇）</td></tr><tr><td><code>public</code></td><td>任何人</td></tr></tbody></table></section>
<section><h2>三、构造函数详解<a href="#三构造函数详解"><span>#</span></a></h2><section><h3>重载与默认构造<a href="#重载与默认构造"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Date</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> </span><span>y</span><span>, </span><span>m</span><span>, </span><span>d</span><span>;</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Date</span><span>() : </span><span>y</span><span>(</span><span>2026</span><span>), </span><span>m</span><span>(</span><span>1</span><span>), </span><span>d</span><span>(</span><span>1</span><span>) {}</span><span>                 // 默认构造</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Date</span><span>(</span><span>int</span><span><span> </span><span>y</span><span>, </span></span><span>int</span><span><span> </span><span>m</span><span>, </span></span><span>int</span><span><span> </span><span>d</span><span>) : </span></span><span>y</span><span>(</span><span>y</span><span>), </span><span>m</span><span>(</span><span>m</span><span>), </span><span>d</span><span>(</span><span>d</span><span>) {}</span><span> // 三参构造</span></div></div><div><div><div>6</div></div><div><span>    </span><span>explicit</span><span> </span><span>Date</span><span>(</span><span>int</span><span><span> </span><span>days</span><span>) {</span></span><span>                        // 单参构造加 explicit（见下）</span></div></div><div><div><div>7</div></div><div><span>        </span><span>y</span><span> </span><span>=</span><span> </span><span>days</span><span> </span><span>/</span><span> </span><span>365</span><span> </span><span>+</span><span> </span><span>1970</span><span>; </span><span>m</span><span> </span><span>=</span><span> </span><span>1</span><span>; </span><span>d</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>Date</span><span> </span><span>a</span><span>;</span><span>              // 默认构造（注意：不带括号！）</span></div></div><div><div><div>12</div></div><div><span>Date</span><span> </span><span>b</span><span>{</span><span>2026</span><span>, </span><span>10</span><span>, </span><span>29</span><span>};</span></div></div><div><div><div>13</div></div><div><span>Date</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>Date</span><span>(</span><span>2026</span><span>, </span><span>10</span><span>, </span><span>29</span><span>);</span></div></div><div><div><div>14</div></div><div><span>// Date d();         // ⚠ 经典陷阱：这是函数声明，不是构造对象！</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>explicit：防止单参构造的隐式转换<a href="#explicit防止单参构造的隐式转换"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>print</span><span>(</span><span>const</span><span> </span><span>Date</span><span>&amp;</span><span><span> </span><span>d</span><span>);</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// 若 Date(int) 不加 explicit：</span></div></div><div><div><div>4</div></div><div><span>// print(12345);    // 会被悄悄转换成 Date——意外行为！</span></div></div><div><div><div>5</div></div><div><span>// 加了 explicit 后必须显式：print(Date(12345));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>军规：单参构造一律加 explicit</strong>。</p></section><section><h3>委托构造与 default（C++11）<a href="#委托构造与-defaultc11"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Widget</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Widget</span><span>() : </span><span>Widget</span><span>(</span><span>0</span><span>, </span><span>0</span><span>) {}</span><span>          // 委托给另一个构造</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Widget</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>, </span></span><span>int</span><span><span> </span><span>y</span><span>) : </span></span><span>x_</span><span>(</span><span>x</span><span>), </span><span>y_</span><span>(</span><span>y</span><span>) {}</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Widget</span><span>(</span><span>const</span><span> </span><span>Widget</span><span>&amp;</span><span>) </span><span>=</span><span> </span><span>default</span><span>;</span><span>    // 让编译器生成默认版本</span></div></div><div><div><div>6</div></div><div><span>private:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>int</span><span> </span><span>x_</span><span>, </span><span>y_</span><span>;</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、析构函数<a href="#四析构函数"><span>#</span></a></h2><p>对象销毁时自动调用，名字是 <code>~类名</code>，负责清理资源：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>class</span><span> </span><span>FileLogger</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>FILE</span><span>*</span><span> </span><span>fp</span><span>;</span></div></div><div><div><div>5</div></div><div><span>public:</span></div></div><div><div><div>6</div></div><div><span>    </span><span>FileLogger</span><span>(</span><span>const</span><span> </span><span>char*</span><span><span> </span><span>path</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>fp</span><span> </span><span>=</span><span> </span><span>fopen</span><span>(</span><span>path</span><span>, </span><span>"a"</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"[打开日志]</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>    </span><span>void</span><span> </span><span>log</span><span>(</span><span>const</span><span> </span><span>char*</span><span><span> </span><span>msg</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span> (</span><span>fp</span><span>) </span><span>fprintf</span><span>(</span><span>fp</span><span>, </span><span>"</span><span>%s</span><span>\n</span><span>"</span><span>, </span><span>msg</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>    </span><span>~FileLogger</span><span>() {</span><span>                     // 析构：对象生命周期结束时自动调用</span></div></div><div><div><div>16</div></div><div><span>        </span><span>if</span><span> (</span><span>fp</span><span>) </span><span>fclose</span><span>(</span><span>fp</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"[关闭日志]</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>};</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>void</span><span> </span><span>demo</span><span>() {</span></div></div><div><div><div>22</div></div><div><span>    </span><span>FileLogger</span><span> </span><span>logger</span><span>(</span><span>"app.log"</span><span>);</span><span>       // 栈对象：demo 结束自动析构</span></div></div><div><div><div>23</div></div><div><span>    </span><span>logger</span><span>.</span><span>log</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>24</div></div><div><span>}</span><span>                                       // 打印 [关闭日志]——这就是 RAII！</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>int</span><span> </span><span>main</span><span>() { </span><span>demo</span><span>(); std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"demo 之后</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>27</div></div><div><span>// 输出顺序：[打开日志] [关闭日志] demo 之后</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>RAII（资源获取即初始化）</strong>：资源在构造函数获取、析构函数释放——智能指针、锁、文件句柄都靠它。<strong>C++ 程序员最重要的习惯：把资源包进对象，交给析构函数管理</strong>。</p></section>
<section><h2>五、拷贝：三巨头之二<a href="#五拷贝三巨头之二"><span>#</span></a></h2><section><h3>拷贝构造与拷贝赋值<a href="#拷贝构造与拷贝赋值"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Buffer</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int*</span><span> </span><span>data</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>size_t</span><span> </span><span>size</span><span>;</span></div></div><div><div><div>4</div></div><div><span>public:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Buffer</span><span>(</span><span>size_t</span><span><span> </span><span>n</span><span>) : </span></span><span>data</span><span>(</span><span>new</span><span> </span><span>int</span><span>[</span><span>n</span><span>]{}), </span><span>size</span><span>(</span><span>n</span><span>) {}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>// 拷贝构造：用旧对象构造新对象</span></div></div><div><div><div>8</div></div><div><span>    </span><span>Buffer</span><span>(</span><span>const</span><span> </span><span>Buffer</span><span>&amp;</span><span><span> </span><span>other</span><span>)</span></span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>: </span><span>data</span><span>(</span><span>new</span><span> </span><span>int</span><span>[</span><span>other</span><span>.</span><span>size</span><span>]), </span><span>size</span><span>(</span><span>other</span><span>.</span><span>size</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>std::</span><span>copy</span><span>(</span><span>other</span><span>.</span><span>data</span><span>, </span><span>other</span><span>.</span><span>data</span><span> </span><span>+</span><span> </span><span>size</span><span>, </span><span>data</span><span>);</span><span>   // 深拷贝！</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"拷贝构造</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>// 拷贝赋值：旧对象 = 旧对象</span></div></div><div><div><div>15</div></div><div><span>    </span><span>Buffer</span><span>&amp;</span><span> </span><span>operator</span><span>=(</span><span>const</span><span> </span><span>Buffer</span><span>&amp;</span><span><span> </span><span>other</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span>        </span><span>if</span><span> (</span><span>this</span><span> </span><span>!=</span><span> </span><span>&amp;</span><span>other</span><span>) {</span><span>          // 防自赋值 a = a</span></div></div><div><div><div>17</div></div><div><span>            </span><span>delete[]</span><span> </span><span>data</span><span>;</span><span>             // 先释放旧资源</span></div></div><div><div><div>18</div></div><div><span>            </span><span>size</span><span> </span><span>=</span><span> </span><span>other</span><span>.</span><span>size</span><span>;</span></div></div><div><div><div>19</div></div><div><span>            </span><span>data</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>int</span><span>[</span><span>size</span><span>];</span></div></div><div><div><div>20</div></div><div><span><span>            </span></span><span>std::</span><span>copy</span><span>(</span><span>other</span><span>.</span><span>data</span><span>, </span><span>other</span><span>.</span><span>data</span><span> </span><span>+</span><span> </span><span>size</span><span>, </span><span>data</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>        </span><span>return</span><span> </span><span>*</span><span>this</span><span>;</span><span>                  // 返回自身支持链式 a=b=c</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>    </span><span>~Buffer</span><span>() { </span><span>delete[]</span><span> </span><span>data</span><span>; }</span><span>       // 三巨头之三</span></div></div><div><div><div>26</div></div><div><span>};</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>Buffer</span><span> </span><span>a</span><span>(</span><span>10</span><span>);</span></div></div><div><div><div>29</div></div><div><span>Buffer</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>a</span><span>;</span><span>        // 拷贝构造（定义时初始化）</span></div></div><div><div><div>30</div></div><div><span>Buffer</span><span> </span><span>c</span><span>(</span><span>5</span><span>);</span></div></div><div><div><div>31</div></div><div><span>c</span><span> </span><span>=</span><span> </span><span>a</span><span>;</span><span>               // 拷贝赋值（已存在对象赋值）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>浅拷贝的灾难（编译器默认拷贝的坑）<a href="#浅拷贝的灾难编译器默认拷贝的坑"><span>#</span></a></h3><p>若不写拷贝构造，编译器生成<strong>逐成员浅拷贝</strong>——指针成员只拷贝地址：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 假设 Buffer 没写拷贝构造：</span></div></div><div><div><div>2</div></div><div><span>Buffer</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>a</span><span>;</span><span>        // b.data 与 a.data 指向同一块内存！</span></div></div><div><div><div>3</div></div><div><span>// 析构时：a、b 各 delete 同一块内存 → 💥 双重释放，程序崩溃</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>规则</strong>：类持有裸资源（指针/文件句柄）就必须遵循<strong>三法则</strong>：自定义析构、拷贝构造、拷贝赋值（或全部 = delete 禁止拷贝）。</p></section><section><h3>移动语义预告（C++11）<a href="#移动语义预告c11"><span>#</span></a></h3><p>深拷贝大 Buffer 很浪费，C++11 引入移动：<code>Buffer d = std::move(a);</code> 直接”偷”走 a 的资源不复制。进阶内容，此处知道有这回事即可。</p></section></section>
<section><h2>六、static 成员与 this<a href="#六static-成员与-this"><span>#</span></a></h2><section><h3>static：属于类而非对象<a href="#static属于类而非对象"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Counter</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Counter</span><span>() { </span><span>++</span><span>count_</span><span>; }</span></div></div><div><div><div>4</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>get_count</span><span>() { </span><span>return</span><span> </span><span>count_</span><span>; }</span><span>    // 静态成员函数：无 this</span></div></div><div><div><div>5</div></div><div><span>private:</span></div></div><div><div><div>6</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>count_</span><span>;</span><span>           // 静态成员变量：所有对象共享一份</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>int</span><span> Counter::</span><span>count_</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>         // ⚠ 类外定义（C++17 可 inline static int count_ = 0;）</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>Counter</span><span> </span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>;</span></div></div><div><div><div>11</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> Counter::</span><span>get_count</span><span>();</span><span>   // 3（用类名调用，不需要对象）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>this 指针<a href="#this-指针"><span>#</span></a></h3><p>每个成员函数都隐含 <code>this</code>（指向当前对象的指针）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Chain</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> </span><span>value</span><span>;</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Chain</span><span>&amp;</span><span> </span><span>add</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>) {</span></span><span>       // 返回 *this 实现链式调用</span></div></div><div><div><div>5</div></div><div><span>        </span><span>value</span><span> </span><span>+=</span><span> </span><span>x</span><span>;</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>*</span><span>this</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>Chain</span><span> </span><span>c</span><span>;</span></div></div><div><div><div>11</div></div><div><span>c</span><span>.</span><span>add</span><span>(</span><span>1</span><span>).</span><span>add</span><span>(</span><span>2</span><span>).</span><span>add</span><span>(</span><span>3</span><span>);</span><span>       // 链式：value = 6</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>七、常量成员与 mutable<a href="#七常量成员与-mutable"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Temp</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>mutable</span><span> </span><span>int</span><span> </span><span>access_count</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>    // mutable：const 函数里也可改</span></div></div><div><div><div>3</div></div><div><span>    </span><span>double</span><span> </span><span>celsius_</span><span> </span><span>=</span><span> </span><span>25.0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>public:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>double</span><span> </span><span>fahrenheit</span><span>() </span><span>const</span><span> {</span><span>      // const 成员函数：保证不改成员</span></div></div><div><div><div>6</div></div><div><span>        </span><span>++</span><span>access_count</span><span>;</span><span>              // ✓ mutable 例外</span></div></div><div><div><div>7</div></div><div><span>        </span><span>return</span><span> </span><span>celsius_</span><span> </span><span>*</span><span> </span><span>9</span><span> </span><span>/</span><span> </span><span>5</span><span> </span><span>+</span><span> </span><span>32</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>Temp</span><span> </span><span>t</span><span>;</span><span>        // const 对象只能调用 const 成员函数</span></div></div><div><div><div>12</div></div><div><span>t</span><span>.</span><span>fahrenheit</span><span>();</span><span>      // ✓</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>规则</strong>：不修改成员的函数一律标 <code>const</code>——否则 const 对象/引用调不了它，STL 里会到处报错。</p></section>
<section><h2>八、实战：矩阵类<a href="#八实战矩阵类"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;stdexcept&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;iomanip&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>class</span><span> </span><span>Matrix</span><span> {</span></div></div><div><div><div>7</div></div><div><span>public:</span></div></div><div><div><div>8</div></div><div><span>    </span><span>Matrix</span><span>(</span><span>size_t</span><span><span> </span><span>rows</span><span>, </span></span><span>size_t</span><span><span> </span><span>cols</span><span>, </span></span><span>double</span><span><span> </span><span>init</span><span> </span></span><span>=</span><span> </span><span>0</span><span>)</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>: </span><span>rows_</span><span>(</span><span>rows</span><span>), </span><span>cols_</span><span>(</span><span>cols</span><span>), </span><span>data_</span><span>(</span><span>rows</span><span> </span><span>*</span><span> </span><span>cols</span><span>, </span><span>init</span><span>) {}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>    </span><span>double&amp;</span><span> </span><span>at</span><span>(</span><span>size_t</span><span><span> </span><span>r</span><span>, </span></span><span>size_t</span><span><span> </span><span>c</span><span>) {</span></span><span>            // 可写访问（带越界检查）</span></div></div><div><div><div>12</div></div><div><span>        </span><span>check</span><span>(</span><span>r</span><span>, </span><span>c</span><span>);</span></div></div><div><div><div>13</div></div><div><span>        </span><span>return</span><span> </span><span>data_</span><span>[</span><span>r</span><span> </span><span>*</span><span> </span><span>cols_</span><span> </span><span>+</span><span> </span><span>c</span><span>];</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>    </span><span>double</span><span> </span><span>at</span><span>(</span><span>size_t</span><span><span> </span><span>r</span><span>, </span></span><span>size_t</span><span><span> </span><span>c</span><span>) </span></span><span>const</span><span> {</span><span>       // 只读访问（重载）</span></div></div><div><div><div>16</div></div><div><span>        </span><span>check</span><span>(</span><span>r</span><span>, </span><span>c</span><span>);</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span> </span><span>data_</span><span>[</span><span>r</span><span> </span><span>*</span><span> </span><span>cols_</span><span> </span><span>+</span><span> </span><span>c</span><span>];</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>size_t</span><span> </span><span>rows</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>rows_</span><span>; }</span></div></div><div><div><div>21</div></div><div><span>    </span><span>size_t</span><span> </span><span>cols</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>cols_</span><span>; }</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>    </span><span>Matrix</span><span> </span><span>operator</span><span>*(</span><span>const</span><span> </span><span>Matrix</span><span>&amp;</span><span><span> </span><span>rhs</span><span>) </span></span><span>const</span><span> {</span><span> // 运算符重载：矩阵乘法</span></div></div><div><div><div>24</div></div><div><span>        </span><span>if</span><span> (</span><span>cols_</span><span> </span><span>!=</span><span> </span><span>rhs</span><span>.</span><span>rows_</span><span>)</span></div></div><div><div><div>25</div></div><div><span>            </span><span>throw</span><span> std::</span><span>invalid_argument</span><span>(</span><span>"尺寸不匹配"</span><span>);</span></div></div><div><div><div>26</div></div><div><span>        </span><span>Matrix</span><span> </span><span>result</span><span>(</span><span>rows_</span><span>, </span><span>rhs</span><span>.</span><span>cols_</span><span>);</span></div></div><div><div><div>27</div></div><div><span>        </span><span>for</span><span> (</span><span>size_t</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>rows_</span><span>; </span><span>++</span><span>i</span><span>)</span></div></div><div><div><div>28</div></div><div><span>            </span><span>for</span><span> (</span><span>size_t</span><span> </span><span>k</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>k</span><span> </span><span>&lt;</span><span> </span><span>cols_</span><span>; </span><span>++</span><span>k</span><span>)</span></div></div><div><div><div>29</div></div><div><span>                </span><span>for</span><span> (</span><span>size_t</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>rhs</span><span>.</span><span>cols_</span><span>; </span><span>++</span><span>j</span><span>)</span></div></div><div><div><div>30</div></div><div><span>                    </span><span>result</span><span>.</span><span>at</span><span>(</span><span>i</span><span>, </span><span>j</span><span>) </span><span>+=</span><span> </span><span>at</span><span>(</span><span>i</span><span>, </span><span>k</span><span>) </span><span>*</span><span> </span><span>rhs</span><span>.</span><span>at</span><span>(</span><span>k</span><span>, </span><span>j</span><span>);</span></div></div><div><div><div>31</div></div><div><span>        </span><span>return</span><span> </span><span>result</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>    </span><span>void</span><span> </span><span>print</span><span>() </span><span>const</span><span> {</span></div></div><div><div><div>35</div></div><div><span>        </span><span>for</span><span> (</span><span>size_t</span><span> </span><span>i</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>i</span><span> </span><span>&lt;</span><span> </span><span>rows_</span><span>; </span><span>++</span><span>i</span><span>) {</span></div></div><div><div><div>36</div></div><div><span>            </span><span>for</span><span> (</span><span>size_t</span><span> </span><span>j</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>j</span><span> </span><span>&lt;</span><span> </span><span>cols_</span><span>; </span><span>++</span><span>j</span><span>)</span></div></div><div><div><div>37</div></div><div><span><span>                </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>setw</span><span>(</span><span>8</span><span>) </span><span>&lt;&lt;</span><span> </span><span>at</span><span>(</span><span>i</span><span>, </span><span>j</span><span>);</span></div></div><div><div><div>38</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>private:</span></div></div><div><div><div>43</div></div><div><span>    </span><span>void</span><span> </span><span>check</span><span>(</span><span>size_t</span><span><span> </span><span>r</span><span>, </span></span><span>size_t</span><span><span> </span><span>c</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>44</div></div><div><span>        </span><span>if</span><span> (</span><span>r</span><span> </span><span>&gt;=</span><span> </span><span>rows_</span><span> </span><span>||</span><span> </span><span>c</span><span> </span><span>&gt;=</span><span> </span><span>cols_</span><span>)</span></div></div><div><div><div>45</div></div><div><span>            </span><span>throw</span><span> std::</span><span>out_of_range</span><span>(</span><span>"矩阵下标越界"</span><span>);</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>47</div></div><div><span>    </span><span>size_t</span><span> </span><span>rows_</span><span>, </span><span>cols_</span><span>;</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>double</span><span>&gt; </span><span>data_</span><span>;</span></div></div><div><div><div>49</div></div><div><span>};</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>52</div></div><div><span>    </span><span>Matrix</span><span> </span><span>a</span><span>(</span><span>2</span><span>, </span><span>3</span><span>, </span><span>1.0</span><span>);</span></div></div><div><div><div>53</div></div><div><span>    </span><span>Matrix</span><span> </span><span>b</span><span>(</span><span>3</span><span>, </span><span>2</span><span>, </span><span>2.0</span><span>);</span></div></div><div><div><div>54</div></div><div><span>    </span><span>Matrix</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>*</span><span> </span><span>b</span><span>;</span><span>        // 6 = 全1×全2</span></div></div><div><div><div>55</div></div><div><span>    </span><span>c</span><span>.</span><span>print</span><span>();</span></div></div><div><div><div>56</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>用到的本篇知识：构造初始化列表、private 封装、const 成员函数重载、运算符重载、异常（第十一篇详讲）。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>实现 <code>Fraction</code>（分数类）：私有分子分母、<code>reduce()</code> 约分、<code>operator+</code>、<code>print()</code>，保证分母永不为 0</li>
<li>给第三篇的猜数字加 <code>GameStats</code> 类：static 成员统计总局数与总尝试次数</li>
<li>写 <code>Timer</code> 类：构造记录时间、析构时打印存活时长（RAII 计时器，函数性能粗测神器）</li>
<li>实现 <code>Stack</code> 类（基于 vector）：push/pop/top/empty/size，pop 空栈时抛异常</li>
<li>（概念）说出三法则是什么、为什么持有 <code>int*</code> 的类必须遵守</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>class 默认 private；封装 = 数据私有 + 接口公开</li>
<li>构造函数可重载；初始化列表先于构造体执行；单参构造加 explicit</li>
<li>析构 <code>~T()</code> 自动释放资源——RAII 是 C++ 的核心习惯</li>
<li>浅拷贝会双重释放；持有资源遵循三法则（析构+拷贝构造+拷贝赋值）</li>
<li>static 成员类共享；this 支持链式；只读函数标 const</li>
</ul><p><strong>下一篇</strong>：面向对象（下）——继承、多态与虚函数，OOP 的另一半拼图。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。三法则与 RAII 是 C++ 区别于其他语言的核心概念，值得反复咀嚼。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-09/</id>
      <title type="text">C++ 入门教程（九）：面向对象（下）——继承与多态</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-09/"/>
      <summary type="text">讲透 C++ 继承体系：派生类构造顺序、protected 访问、虚函数与动态绑定原理、override 与 final、纯虚函数与抽象类、虚析构函数、多态实战图形系统与怪奇物语。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>OOP 三大特性的另外两个：<strong>继承</strong>（代码复用的层级体系）与<strong>多态</strong>（同一接口、不同行为）。虚函数是 C++ 多态的核心机制，也是面试必考。本篇讲透它的语法与原理。</p></section>
<section><h2>一、继承基础<a href="#一继承基础"><span>#</span></a></h2><section><h3>基本语法<a href="#基本语法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 基类（父类）</span></div></div><div><div><div>5</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>6</div></div><div><span>public:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Animal</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>) : </span></span><span>name_</span><span>(</span><span>name</span><span>) {}</span></div></div><div><div><div>8</div></div><div><span>    </span><span>void</span><span> </span><span>eat</span><span>() </span><span>const</span><span> { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"在吃东西</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>9</div></div><div><span>protected:</span><span>                      // 子类可访问，外部不行</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name_</span><span>;</span></div></div><div><div><div>11</div></div><div><span>};</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 派生类（子类）：public 继承表示"是一个"关系</span></div></div><div><div><div>14</div></div><div><span>class</span><span> </span><span>Dog</span><span> : </span><span>public</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>15</div></div><div><span>public:</span></div></div><div><div><div>16</div></div><div><span>    </span><span>Dog</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>, </span></span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>breed</span><span>)</span></span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>: </span><span>Animal</span><span>(</span><span>name</span><span>), </span><span>breed_</span><span>(</span><span>breed</span><span>) {}</span><span>       // ⚠ 先调基类构造</span></div></div><div><div><div>18</div></div><div><span>    </span><span>void</span><span> </span><span>fetch</span><span>() </span><span>const</span><span> { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"去捡球</span><span>\n</span><span>"</span><span>; }</span><span>   // 直接用 protected 成员</span></div></div><div><div><div>19</div></div><div><span>private:</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>breed_</span><span>;</span></div></div><div><div><div>21</div></div><div><span>};</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>class</span><span> </span><span>Cat</span><span> : </span><span>public</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>24</div></div><div><span>public:</span></div></div><div><div><div>25</div></div><div><span>    </span><span>Cat</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>) : </span></span><span>Animal</span><span>(</span><span>name</span><span>) {}</span></div></div><div><div><div>26</div></div><div><span>    </span><span>void</span><span> </span><span>scratch</span><span>() </span><span>const</span><span> { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"在磨爪</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>27</div></div><div><span>};</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>Dog</span><span> </span><span>d</span><span>(</span><span>"旺财"</span><span>, </span><span>"柴犬"</span><span>);</span></div></div><div><div><div>31</div></div><div><span>    </span><span>d</span><span>.</span><span>eat</span><span>();</span><span>       // 继承来的</span></div></div><div><div><div>32</div></div><div><span>    </span><span>d</span><span>.</span><span>fetch</span><span>();</span><span>     // 自己的</span></div></div><div><div><div>33</div></div><div><span>    </span><span>Cat</span><span> </span><span>c</span><span>(</span><span>"咪咪"</span><span>);</span></div></div><div><div><div>34</div></div><div><span>    </span><span>c</span><span>.</span><span>eat</span><span>();</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>三种继承方式</strong>（99% 场景用 public 继承）：</p>

<table><thead><tr><th>继承方式</th><th>基类 public 成员在子类中变为</th><th>基类 protected</th><th>基类 private</th></tr></thead><tbody><tr><td><code>public</code> 继承</td><td>public</td><td>protected</td><td>不可访问</td></tr><tr><td><code>protected</code> 继承</td><td>protected</td><td>protected</td><td>不可访问</td></tr><tr><td><code>private</code> 继承</td><td>private</td><td>private</td><td>不可访问</td></tr></tbody></table></section><section><h3>构造与析构顺序<a href="#构造与析构顺序"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 构造：基类先构造，再派生类</span></div></div><div><div><div>2</div></div><div><span>// 析构：派生类先析构，再基类（完全相反，像穿脱衣服）</span></div></div><div><div><div>3</div></div><div><span>class</span><span> </span><span>Base</span><span> {</span></div></div><div><div><div>4</div></div><div><span>public:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Base</span><span>()  { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Base构造</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>6</div></div><div><span>    </span><span>~Base</span><span>() { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Base析构</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>class</span><span> </span><span>Derived</span><span> : </span><span>public</span><span> </span><span>Base</span><span> {</span></div></div><div><div><div>9</div></div><div><span>public:</span></div></div><div><div><div>10</div></div><div><span>    </span><span>Derived</span><span>()  { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Derived构造</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>11</div></div><div><span>    </span><span>~Derived</span><span>() { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"Derived析构</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div><span>// Derived d; 输出：</span></div></div><div><div><div>14</div></div><div><span>// Base构造 → Derived构造 → Derived析构 → Base析构</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、虚函数与多态（本篇核心）<a href="#二虚函数与多态本篇核心"><span>#</span></a></h2><section><h3>问题引入<a href="#问题引入"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Animal</span><span>*</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span>);</span><span>   // 基类指针指向子类对象（合法）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>现在想让每个动物”叫出自己的声音”：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> {</span><span>                 // ❌ 普通成员函数</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"在发声</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> : </span><span>public</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>8</div></div><div><span>public:</span></div></div><div><div><div>9</div></div><div><span>    </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> {</span><span>                 // 隐藏（不是重写！）</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"汪汪！</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>Animal</span><span>*</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span>);</span></div></div><div><div><div>15</div></div><div><span>a</span><span>-&gt;</span><span>speak</span><span>();</span><span>      // 输出"旺财在发声"——调的是基类版本！</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>普通函数调用在<strong>编译期</strong>按指针类型绑定（静态绑定），所以永远调 Animal 的版本。</p></section><section><h3>virtual：运行期绑定<a href="#virtual运行期绑定"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Animal</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>) : </span></span><span>name_</span><span>(</span><span>name</span><span>) {}</span></div></div><div><div><div>4</div></div><div><span>    </span><span>virtual</span><span> </span><span>~Animal</span><span>() </span><span>=</span><span> </span><span>default</span><span>;</span><span>         // ⚠ 虚析构（后面讲为什么）</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>virtual</span><span> </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> {</span><span>         // virtual 声明为虚函数</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"在发声</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>protected:</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name_</span><span>;</span></div></div><div><div><div>11</div></div><div><span>};</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>class</span><span> </span><span>Dog</span><span> : </span><span>public</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>14</div></div><div><span>public:</span></div></div><div><div><div>15</div></div><div><span>    </span><span>Dog</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>n</span><span>) : </span></span><span>Animal</span><span>(</span><span>n</span><span>) {}</span></div></div><div><div><div>16</div></div><div><span>    </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> </span><span>override</span><span> {</span><span>        // override 显式标记重写（C++11）</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"汪汪！</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>};</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>class</span><span> </span><span>Cat</span><span> : </span><span>public</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>22</div></div><div><span>public:</span></div></div><div><div><div>23</div></div><div><span>    </span><span>Cat</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>n</span><span>) : </span></span><span>Animal</span><span>(</span><span>n</span><span>) {}</span></div></div><div><div><div>24</div></div><div><span>    </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> </span><span>override</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>"喵～</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>};</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>Animal</span><span>*</span><span> </span><span>zoo</span><span>[] </span><span>=</span><span> {</span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span>), </span><span>new</span><span> </span><span>Cat</span><span>(</span><span>"咪咪"</span><span>)};</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>    </span><span>for</span><span> (</span><span>Animal</span><span>*</span><span> </span><span>a</span><span> : </span><span>zoo</span><span>)</span></div></div><div><div><div>33</div></div><div><span>        </span><span>a</span><span>-&gt;</span><span>speak</span><span>();</span><span>          // ✅ 汪汪！/ 喵～ 运行期按真实类型绑定！</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>    </span><span>for</span><span> (</span><span>Animal</span><span>*</span><span> </span><span>a</span><span> : </span><span>zoo</span><span>)</span></div></div><div><div><div>36</div></div><div><span>        </span><span>delete</span><span> </span><span>a</span><span>;</span><span>            // 虚析构保证正确释放子类部分</span></div></div><div><div><div>37</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>多态成立的三个条件</strong>：基类函数是 <code>virtual</code>、子类 <code>override</code> 重写、通过<strong>基类指针或引用</strong>调用。</p><div><div><div></div><div>Tip</div></div><div><p><code>override</code> 关键字让编译器帮你检查签名是否真的重写成功（拼错函数名会直接报错）——<strong>重写必写 override</strong>。</p></div></div></section><section><h3>虚函数原理（面试高频，简版）<a href="#虚函数原理面试高频简版"><span>#</span></a></h3><p>每个含虚函数的类都有一张<strong>虚函数表（vtable）</strong>，对象头部存指向 vtable 的指针（vptr）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Animal* a → [vptr] → Animal::vtable  [ &amp;Animal::speak ]</span></div></div><div><div><div>2</div></div><div><span>Dog 对象  → [vptr] → Dog::vtable     [ &amp;Dog::speak    ]   ← Dog 覆盖了槽位</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>调用 a-&gt;speak() 编译为：a-&gt;vptr-&gt;speak槽位()   ← 运行期查表</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>代价：每对象多 8 字节指针 + 一次间接跳转。所以”不需要多态就别加 virtual”。</p></section></section>
<section><h2>三、纯虚函数与抽象类<a href="#三纯虚函数与抽象类"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Shape</span><span> {</span><span>                        // 抽象类：含纯虚函数，不能实例化</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>virtual</span><span> </span><span>double</span><span> </span><span>area</span><span>() </span><span>const</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>     // = 0 纯虚：子类必须实现</span></div></div><div><div><div>4</div></div><div><span>    </span><span>virtual</span><span> </span><span>~Shape</span><span>() </span><span>=</span><span> </span><span>default</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>// 可以有普通成员与实现</span></div></div><div><div><div>7</div></div><div><span>    </span><span>void</span><span> </span><span>describe</span><span>() </span><span>const</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"面积 = "</span><span> </span><span>&lt;&lt;</span><span> </span><span>area</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 调用延迟到子类</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>class</span><span> </span><span>Circle</span><span> : </span><span>public</span><span> </span><span>Shape</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>double</span><span> </span><span>r</span><span>;</span></div></div><div><div><div>14</div></div><div><span>public:</span></div></div><div><div><div>15</div></div><div><span>    </span><span>explicit</span><span> </span><span>Circle</span><span>(</span><span>double</span><span><span> </span><span>r</span><span>) : </span></span><span>r</span><span>(</span><span>r</span><span>) {}</span></div></div><div><div><div>16</div></div><div><span>    </span><span>double</span><span> </span><span>area</span><span>() </span><span>const</span><span> </span><span>override</span><span> { </span><span>return</span><span> </span><span>3.14159</span><span> </span><span>*</span><span> </span><span>r</span><span> </span><span>*</span><span> </span><span>r</span><span>; }</span></div></div><div><div><div>17</div></div><div><span>};</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>class</span><span> </span><span>Rect</span><span> : </span><span>public</span><span> </span><span>Shape</span><span> {</span></div></div><div><div><div>20</div></div><div><span>    </span><span>double</span><span> </span><span>w</span><span>, </span><span>h</span><span>;</span></div></div><div><div><div>21</div></div><div><span>public:</span></div></div><div><div><div>22</div></div><div><span>    </span><span>Rect</span><span>(</span><span>double</span><span><span> </span><span>w</span><span>, </span></span><span>double</span><span><span> </span><span>h</span><span>) : </span></span><span>w</span><span>(</span><span>w</span><span>), </span><span>h</span><span>(</span><span>h</span><span>) {}</span></div></div><div><div><div>23</div></div><div><span>    </span><span>double</span><span> </span><span>area</span><span>() </span><span>const</span><span> </span><span>override</span><span> { </span><span>return</span><span> </span><span>w</span><span> </span><span>*</span><span> </span><span>h</span><span>; }</span></div></div><div><div><div>24</div></div><div><span>};</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>// Shape s;              // ❌ 抽象类不能造对象</span></div></div><div><div><div>27</div></div><div><span>// Shape* p = new Shape; // ❌ 同上</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>Shape</span><span>*</span><span> </span><span>shapes</span><span>[] </span><span>=</span><span> {</span><span>new</span><span> </span><span>Circle</span><span>(</span><span>2</span><span>), </span><span>new</span><span> </span><span>Rect</span><span>(</span><span>3</span><span>, </span><span>4</span><span>)};</span></div></div><div><div><div>31</div></div><div><span>    </span><span>double</span><span> </span><span>total</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>32</div></div><div><span>    </span><span>for</span><span> (</span><span>auto*</span><span> </span><span>s</span><span> : </span><span>shapes</span><span>) {</span></div></div><div><div><div>33</div></div><div><span>        </span><span>s</span><span>-&gt;</span><span>describe</span><span>();</span><span>           // 多态：各算各的面积</span></div></div><div><div><div>34</div></div><div><span>        </span><span>total</span><span> </span><span>+=</span><span> </span><span>s</span><span>-&gt;</span><span>area</span><span>();</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"总面积 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>total</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>37</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>抽象类 = 接口契约</strong>：规定”所有 Shape 必须会算面积”，实现交给子类。纯虚析构除外，接口类通常只含纯虚函数。</p></section>
<section><h2>四、虚析构函数（必考）<a href="#四虚析构函数必考"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>BadBase</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>~BadBase</span><span>() { std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"~BadBase</span><span>\n</span><span>"</span><span>; }</span><span>    // ❌ 非虚析构</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>class</span><span> </span><span>BadDerived</span><span> : </span><span>public</span><span> </span><span>BadBase</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>int*</span><span> </span><span>big_</span><span>;</span></div></div><div><div><div>7</div></div><div><span>public:</span></div></div><div><div><div>8</div></div><div><span>    </span><span>BadDerived</span><span>() : </span><span>big_</span><span>(</span><span>new</span><span> </span><span>int</span><span>[</span><span>1000</span><span>]) {}</span></div></div><div><div><div>9</div></div><div><span>    </span><span>~BadDerived</span><span>() { </span><span>delete[]</span><span> </span><span>big_</span><span>; std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"~BadDerived</span><span>\n</span><span>"</span><span>; }</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>BadBase</span><span>*</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>BadDerived</span><span>();</span></div></div><div><div><div>14</div></div><div><span>    </span><span>delete</span><span> </span><span>p</span><span>;</span><span>      // ⚠ 只输出 ~BadBase！子类析构没执行 → big_ 泄漏 4000 字节</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>修正</strong>：基类析构函数声明为 <code>virtual ~Base() = default;</code>。<strong>军规：只要类会被继承且通过基类指针删除，析构必须是 virtual</strong>。</p></section>
<section><h2>五、final 与类型识别<a href="#五final-与类型识别"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Locked</span><span> : </span><span>public</span><span> </span><span>Base</span><span> {</span></div></div><div><div><div>2</div></div><div><span>public:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>void</span><span> </span><span>speak</span><span>() </span><span>const</span><span> </span><span>final</span><span>;</span><span>      // final：禁止后代再重写</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>// class Sub : public Locked {};  // 也可 final 整个类：禁止再继承</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 运行期类型识别 dynamic_cast（向下转型，需多态类型）</span></div></div><div><div><div>8</div></div><div><span>Animal</span><span>*</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>if</span><span> (</span><span>Dog</span><span>*</span><span> </span><span>d</span><span> </span><span>=</span><span> </span><span><span>dynamic_cast</span><span>&lt;</span></span><span>Dog</span><span>*&gt;</span><span>(</span><span>a</span><span>)) {</span><span>   // 成功返回指针，失败返回 nullptr</span></div></div><div><div><div>10</div></div><div><span>    </span><span>d</span><span>-&gt;</span><span>fetch</span><span>();</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// typeid 拿到真实类型名</span></div></div><div><div><div>14</div></div><div><span>#include</span><span> </span><span>&lt;typeinfo&gt;</span></div></div><div><div><div>15</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>typeid</span><span>(</span><span>*</span><span>a</span><span>).</span><span>name</span><span>();</span><span>         // 3Dog（名字修饰因编译器而异）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>六、综合实战：RPG 战斗模拟器<a href="#六综合实战rpg-战斗模拟器"><span>#</span></a></h2><p>综合继承+多态+虚析构+抽象类：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;memory&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>5</div></div><div><span>#include</span><span> </span><span>&lt;random&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Character</span><span> {</span><span>                          // 抽象基类</span></div></div><div><div><div>8</div></div><div><span>public:</span></div></div><div><div><div>9</div></div><div><span>    </span><span>Character</span><span>(std::</span><span>string</span><span><span> </span><span>name</span><span>, </span></span><span>int</span><span><span> </span><span>hp</span><span>, </span></span><span>int</span><span><span> </span><span>atk</span><span>)</span></span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>: </span><span>name_</span><span><span>(</span><span>std</span><span>::</span></span><span>move</span><span>(</span><span>name</span><span>)), </span><span>hp_</span><span>(</span><span>hp</span><span>), </span><span>atk_</span><span>(</span><span>atk</span><span>) {}</span></div></div><div><div><div>11</div></div><div><span>    </span><span>virtual</span><span> </span><span>~Character</span><span>() </span><span>=</span><span> </span><span>default</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>    </span><span>virtual</span><span> </span><span>void</span><span> </span><span>attack</span><span>(</span><span>Character</span><span>&amp;</span><span><span> </span><span>target</span><span>) </span></span><span>const</span><span> </span><span>=</span><span> </span><span>0</span><span>;</span><span>   // 纯虚：每种角色攻击方式不同</span></div></div><div><div><div>14</div></div><div><span>    </span><span>virtual</span><span> </span><span>void</span><span> </span><span>take_damage</span><span>(</span><span>int</span><span><span> </span><span>dmg</span><span>) {</span></span></div></div><div><div><div>15</div></div><div><span>        </span><span>hp_</span><span> </span><span>-=</span><span> </span><span>dmg</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"  "</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 受到 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>dmg</span></div></div><div><div><div>17</div></div><div><span>                  </span><span>&lt;&lt;</span><span> </span><span>" 伤害（剩 "</span><span> </span><span>&lt;&lt;</span><span> (</span><span>hp_</span><span> </span><span>&gt;</span><span> </span><span>0</span><span> </span><span>?</span><span> </span><span>hp_</span><span> </span><span>:</span><span> </span><span>0</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"）</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>bool</span><span> </span><span>alive</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>hp_</span><span> </span><span>&gt;</span><span> </span><span>0</span><span>; }</span></div></div><div><div><div>21</div></div><div><span>    </span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span> </span><span>name</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>name_</span><span>; }</span></div></div><div><div><div>22</div></div><div><span>    </span><span>int</span><span> </span><span>atk</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>atk_</span><span>; }</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>protected:</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name_</span><span>;</span></div></div><div><div><div>26</div></div><div><span>    </span><span>int</span><span> </span><span>hp_</span><span>, </span><span>atk_</span><span>;</span></div></div><div><div><div>27</div></div><div><span>};</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>class</span><span> </span><span>Warrior</span><span> : </span><span>public</span><span> </span><span>Character</span><span> {</span><span>         // 战士：稳定输出</span></div></div><div><div><div>30</div></div><div><span>public:</span></div></div><div><div><div>31</div></div><div><span>    </span><span>Warrior</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>n</span><span>) : </span></span><span>Character</span><span>(</span><span>n</span><span>, </span><span>120</span><span>, </span><span>15</span><span>) {}</span></div></div><div><div><div>32</div></div><div><span>    </span><span>void</span><span> </span><span>attack</span><span>(</span><span>Character</span><span>&amp;</span><span><span> </span><span>t</span><span>) </span></span><span>const</span><span> </span><span>override</span><span> {</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 挥剑攻击 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>t</span><span>.</span><span>name</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"！</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>34</div></div><div><span>        </span><span>t</span><span>.</span><span>take_damage</span><span>(</span><span>atk</span><span>());</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span>};</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>class</span><span> </span><span>Mage</span><span> : </span><span>public</span><span> </span><span>Character</span><span> {</span><span>            // 法师：30% 概率暴击</span></div></div><div><div><div>39</div></div><div><span>public:</span></div></div><div><div><div>40</div></div><div><span>    </span><span>Mage</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>n</span><span>) : </span></span><span>Character</span><span>(</span><span>n</span><span>, </span><span>80</span><span>, </span><span>25</span><span>) {}</span></div></div><div><div><div>41</div></div><div><span>    </span><span>void</span><span> </span><span>attack</span><span>(</span><span>Character</span><span>&amp;</span><span><span> </span><span>t</span><span>) </span></span><span>const</span><span> </span><span>override</span><span> {</span></div></div><div><div><div>42</div></div><div><span>        </span><span>static</span><span> std::</span><span>mt19937</span><span> </span><span>rng</span><span>{std::</span><span>random_device</span><span>{}()};</span></div></div><div><div><div>43</div></div><div><span>        </span><span>bool</span><span> </span><span>crit</span><span> </span><span>=</span><span> std::</span><span>uniform_int_distribution</span><span>&lt;&gt;(</span><span>1</span><span>, </span><span>10</span><span>)(</span><span>rng</span><span>) </span><span>&lt;=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>44</div></div><div><span>        </span><span>int</span><span> </span><span>dmg</span><span> </span><span>=</span><span> </span><span>atk</span><span>() </span><span>*</span><span> (</span><span>crit</span><span> </span><span>?</span><span> </span><span>2</span><span> </span><span>:</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name_</span><span> </span><span>&lt;&lt;</span><span> (</span><span>crit</span><span> </span><span>?</span><span> </span><span>" 释放暴击火球！"</span><span> </span><span>:</span><span> </span><span>" 释放火球"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>46</div></div><div><span>        </span><span>t</span><span>.</span><span>take_damage</span><span>(</span><span>dmg</span><span>);</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>48</div></div><div><span>};</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>// 智能指针数组管理多态对象</span></div></div><div><div><div>52</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;std::</span><span>unique_ptr</span><span>&lt;</span><span>Character</span><span>&gt;&gt; </span><span>team</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>53</div></div><div><span><span>        </span></span><span>std::</span><span>make_unique</span><span>&lt;</span><span>Warrior</span><span>&gt;(</span><span>"勇者"</span><span>),</span></div></div><div><div><div>54</div></div><div><span><span>        </span></span><span>std::</span><span>make_unique</span><span>&lt;</span><span>Mage</span><span>&gt;(</span><span>"大法师"</span><span>),</span></div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>56</div></div><div><span>    </span><span>Character</span><span>*</span><span> </span><span>monster</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Warrior</span><span>(</span><span>"哥布林王"</span><span>);</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>    </span><span>int</span><span> </span><span>round</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>59</div></div><div><span>    </span><span>while</span><span> (</span><span>monster</span><span>-&gt;</span><span>alive</span><span>() </span><span>&amp;&amp;</span></div></div><div><div><div>60</div></div><div><span><span>           </span></span><span>std::</span><span>any_of</span><span>(</span><span>team</span><span>.</span><span>begin</span><span>(), </span><span>team</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>61</div></div><div><span><span>                       </span></span><span>[](</span><span>auto&amp;</span><span><span> </span><span>c</span><span>) { </span></span><span>return</span><span> </span><span>c</span><span>-&gt;</span><span>alive</span><span>(); })) {</span></div></div><div><div><div>62</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"—— 回合 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>round</span><span>++</span><span> </span><span>&lt;&lt;</span><span> </span><span>" ——</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>63</div></div><div><span>        </span><span>for</span><span> (</span><span>auto&amp;</span><span> </span><span>c</span><span> : </span><span>team</span><span>)</span></div></div><div><div><div>64</div></div><div><span>            </span><span>if</span><span> (</span><span>c</span><span>-&gt;</span><span>alive</span><span>() </span><span>&amp;&amp;</span><span> </span><span>monster</span><span>-&gt;</span><span>alive</span><span>())</span></div></div><div><div><div>65</div></div><div><span>                </span><span>c</span><span>-&gt;</span><span>attack</span><span>(</span><span>*</span><span>monster</span><span>);</span><span>        // 多态调用</span></div></div><div><div><div>66</div></div><div><span>        </span><span>if</span><span> (</span><span>monster</span><span>-&gt;</span><span>alive</span><span>())</span></div></div><div><div><div>67</div></div><div><span>            </span><span>monster</span><span>-&gt;</span><span>attack</span><span>(</span><span>*</span><span>team</span><span>[</span><span>0</span><span>]);</span></div></div><div><div><div>68</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>monster</span><span>-&gt;</span><span>alive</span><span>() </span><span>?</span><span> </span><span>"团灭……"</span><span> </span><span>:</span><span> </span><span>"胜利！"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>70</div></div><div><span>    </span><span>delete</span><span> </span><span>monster</span><span>;</span></div></div><div><div><div>71</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>新增”刺客""治疗者”只需继承 Character 实现 attack——<strong>对扩展开放，对修改关闭</strong>，这就是多态的工程价值。</p></section>
<section><h2>七、组合优先原则<a href="#七组合优先原则"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 继承："是一个"（Dog 是 Animal）——强耦合</span></div></div><div><div><div>2</div></div><div><span>// 组合："有一个"（Car 有 Engine）——灵活</span></div></div><div><div><div>3</div></div><div><span>class</span><span> </span><span>Engine</span><span> { </span><span>public:</span><span> </span><span>void</span><span> </span><span>start</span><span>() {} };</span></div></div><div><div><div>4</div></div><div><span>class</span><span> </span><span>Car</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Engine</span><span> </span><span>engine_</span><span>;</span><span>                  // 组合</span></div></div><div><div><div>6</div></div><div><span>public:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>void</span><span> </span><span>start</span><span>() { </span><span>engine_</span><span>.</span><span>start</span><span>(); }</span><span>   // 委托</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>经验法则</strong>：能用组合就用组合，“is-a”关系明确才用继承。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>Shape 体系加 <code>Triangle</code>（三边长，海伦公式）与 <code>Square</code></li>
<li>写 <code>Employee</code> 抽象类 + <code>Manager/Sales</code>：月薪计算方式不同（虚函数 <code>salary()</code>），打印全员工资</li>
<li>给 Character 加 <code>heal(Character&amp;)</code> 接口与 Priest 职业实现治疗</li>
<li>验证虚析构：把 BadBase 析构改成 virtual，观察输出变化</li>
<li>（概念）多态三条件是什么？override 和 final 分别解决什么问题？</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>public 继承表达 is-a；构造先基后派、析构反序</li>
<li>virtual 开启动态绑定：基类指针/引用按真实类型调函数；重写必标 override</li>
<li><code>= 0</code> 定义纯虚 → 抽象类不可实例化，作接口契约</li>
<li>基类析构必 virtual（通过基类指针删除时防泄漏）</li>
<li>dynamic_cast 安全向下转型；组合优先于继承</li>
<li>新增子类不改老代码——开闭原则的 C++ 实现</li>
</ul><p><strong>下一篇</strong>：运算符重载与友元——让自定义类型像内置类型一样自然运算。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。RPG 案例的扩展性实验（加职业不动主逻辑）是多态最好的注脚。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-10/</id>
      <title type="text">C++ 入门教程（十）：运算符重载与友元</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-10/"/>
      <summary type="text">掌握 C++ 特色能力：运算符重载的规则与常用实现（算术/比较/流/下标/函数调用）、成员与非成员重载的选择、friend 友元机制、Matrix 与 Fraction 完整实现，理解何时不该重载。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p><code>a + b</code>、<code>cout &lt;&lt; obj</code>、<code>obj[i]</code>——内置类型天然支持这些运算，<strong>自定义类型也可以</strong>。运算符重载让 <code>Money + Money</code>、<code>Vector * Matrix</code> 写起来像数学公式。这是 C++ 区别于多数语言的特性，用好了代码优雅，用滥了灾难现场。</p></section>
<section><h2>一、基本概念与规则<a href="#一基本概念与规则"><span>#</span></a></h2><section><h3>什么能重载、什么不能<a href="#什么能重载什么不能"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>✅ 可重载：+ - * / % == != &lt; &gt; += -= &lt;&lt; &gt;&gt; &amp;&amp; || ! [] () -&gt; new...</span></div></div><div><div><div>2</div></div><div><span>❌ 不可重载：:: . .* sizeof typeid ?:（三目） .*</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>两条硬规则</strong>：</p><ol>
<li>至少一个操作数是自定义类型（不能重载 <code>int + int</code>）</li>
<li>不能发明新运算符、不能改变优先级与结合性</li>
</ol><p><strong>心法</strong>：重载后的行为要<strong>符合直觉</strong>——<code>+</code> 就该是加法语义。把 <code>+</code> 重载成减法，同事会杀人。</p></section><section><h3>成员 vs 非成员<a href="#成员-vs-非成员"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Money</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>long</span><span> </span><span>cents_</span><span>;</span><span>                        // 用"分"存，避免浮点误差</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>// 成员函数版：左操作数必须是本类</span></div></div><div><div><div>5</div></div><div><span>    </span><span>Money</span><span> </span><span>operator</span><span>+(</span><span>const</span><span> </span><span>Money</span><span>&amp;</span><span><span> </span><span>rhs</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>Money</span><span>(</span><span>cents_</span><span> </span><span>+</span><span> </span><span>rhs</span><span>.</span><span>cents_</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 非成员版（常配友元）：左操作数可以是其他类型</span></div></div><div><div><div>11</div></div><div><span>Money</span><span> </span><span>operator</span><span>-(</span><span>const</span><span> </span><span>Money</span><span>&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>Money</span><span>&amp;</span><span><span> </span><span>b</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span>std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span>, </span><span>const</span><span> </span><span>Money</span><span>&amp;</span><span>);</span><span>   // 流运算符必须非成员</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>选择</strong>：会修改左操作数（<code>+=</code>、<code>=</code>、<code>[]</code>）用成员；对称双目（<code>+</code>、<code>==</code>）与流运算符用非成员。</p></section></section>
<section><h2>二、算术与比较运算符<a href="#二算术与比较运算符"><span>#</span></a></h2><section><h3>完整的 Fraction（分数）实现<a href="#完整的-fraction分数实现"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;numeric&gt;</span><span>      </span><span>// std::gcd</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>class</span><span> </span><span>Fraction</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>long</span><span> </span><span>num_</span><span>, </span><span>den_</span><span>;</span><span>                        // 分子/分母</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>void</span><span> </span><span>reduce</span><span>() {</span><span>                         // 内部工具：约分并规范化符号</span></div></div><div><div><div>8</div></div><div><span>        </span><span>long</span><span> </span><span>g</span><span> </span><span>=</span><span> std::</span><span>gcd</span><span>(</span><span>num_</span><span>, </span><span>den_</span><span>);</span></div></div><div><div><div>9</div></div><div><span>        </span><span>if</span><span> (</span><span>g</span><span> </span><span>!=</span><span> </span><span>0</span><span>) { </span><span>num_</span><span> </span><span>/=</span><span> </span><span>g</span><span>; </span><span>den_</span><span> </span><span>/=</span><span> </span><span>g</span><span>; }</span></div></div><div><div><div>10</div></div><div><span>        </span><span>if</span><span> (</span><span>den_</span><span> </span><span>&lt;</span><span> </span><span>0</span><span>) { </span><span>num_</span><span> </span><span>=</span><span> </span><span>-</span><span>num_</span><span>; </span><span>den_</span><span> </span><span>=</span><span> </span><span>-</span><span>den_</span><span>; }</span><span>   // 分母保持正</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>public:</span></div></div><div><div><div>14</div></div><div><span>    </span><span>Fraction</span><span>(</span><span>long</span><span><span> </span><span>n</span><span>, </span></span><span>long</span><span><span> </span><span>d</span><span> </span></span><span>=</span><span> </span><span>1</span><span>) : </span><span>num_</span><span>(</span><span>n</span><span>), </span><span>den_</span><span>(</span><span>d</span><span>) {</span></div></div><div><div><div>15</div></div><div><span>        </span><span>if</span><span> (</span><span>d</span><span> </span><span>==</span><span> </span><span>0</span><span>) </span><span>throw</span><span> std::</span><span>invalid_argument</span><span>(</span><span>"分母为零"</span><span>);</span></div></div><div><div><div>16</div></div><div><span>        </span><span>reduce</span><span>();</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>// —— 算术：返回新对象，const ——</span></div></div><div><div><div>20</div></div><div><span>    </span><span>Fraction</span><span> </span><span>operator</span><span>+(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>21</div></div><div><span>        </span><span>return</span><span> </span><span>Fraction</span><span>(</span><span>num_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span> </span><span>+</span><span> </span><span>r</span><span>.</span><span>num_</span><span> </span><span>*</span><span> </span><span>den_</span><span>, </span><span>den_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div><span>    </span><span>Fraction</span><span> </span><span>operator</span><span>-(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>24</div></div><div><span>        </span><span>return</span><span> </span><span>Fraction</span><span>(</span><span>num_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span> </span><span>-</span><span> </span><span>r</span><span>.</span><span>num_</span><span> </span><span>*</span><span> </span><span>den_</span><span>, </span><span>den_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span>);</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>    </span><span>Fraction</span><span> </span><span>operator</span><span>*(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>27</div></div><div><span>        </span><span>return</span><span> </span><span>Fraction</span><span>(</span><span>num_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>num_</span><span>, </span><span>den_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span>);</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>    </span><span>Fraction</span><span> </span><span>operator</span><span>/(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>30</div></div><div><span>        </span><span>if</span><span> (</span><span>r</span><span>.</span><span>num_</span><span> </span><span>==</span><span> </span><span>0</span><span>) </span><span>throw</span><span> std::</span><span>invalid_argument</span><span>(</span><span>"除以零"</span><span>);</span></div></div><div><div><div>31</div></div><div><span>        </span><span>return</span><span> </span><span>Fraction</span><span>(</span><span>num_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span>, </span><span>den_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>num_</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>// —— 复合赋值：修改自身，返回 *this 引用 ——</span></div></div><div><div><div>35</div></div><div><span>    </span><span>Fraction</span><span>&amp;</span><span> </span><span>operator</span><span>+=(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) {</span></span></div></div><div><div><div>36</div></div><div><span>        </span><span>return</span><span> </span><span>*</span><span>this</span><span> </span><span>=</span><span> </span><span>*</span><span>this</span><span> </span><span>+</span><span> </span><span>r</span><span>;</span><span>           // 复用 operator+</span></div></div><div><div><div>37</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>// —— 比较：写成一对，其余用逻辑推导 ——</span></div></div><div><div><div>40</div></div><div><span>    </span><span>bool</span><span> </span><span>operator</span><span>==(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>41</div></div><div><span>        </span><span>return</span><span> </span><span>num_</span><span> </span><span>==</span><span> </span><span>r</span><span>.</span><span>num_</span><span> </span><span>&amp;&amp;</span><span> </span><span>den_</span><span> </span><span>==</span><span> </span><span>r</span><span>.</span><span>den_</span><span>;</span><span>   // 已约分，直接比</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>    </span><span>bool</span><span> </span><span>operator</span><span>&lt;(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>44</div></div><div><span>        </span><span>return</span><span> </span><span>num_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>den_</span><span> </span><span>&lt;</span><span> </span><span>r</span><span>.</span><span>num_</span><span> </span><span>*</span><span> </span><span>den_</span><span>;</span></div></div><div><div><div>45</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>    </span><span>double</span><span> </span><span>value</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>double</span><span>(</span><span>num_</span><span>) </span><span>/</span><span> </span><span>den_</span><span>; }</span></div></div><div><div><div>48</div></div><div><span>    </span><span>long</span><span> </span><span>num</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>num_</span><span>; }</span></div></div><div><div><div>49</div></div><div><span>    </span><span>long</span><span> </span><span>den</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>den_</span><span>; }</span></div></div><div><div><div>50</div></div><div><span>};</span></div></div><div><div><div>51</div></div><div>
</div></div><div><div><div>52</div></div><div><span>// 非成员：流输出</span></div></div><div><div><div>53</div></div><div><span>std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span><span> </span><span>os</span><span>, </span></span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>f</span><span>) {</span></span></div></div><div><div><div>54</div></div><div><span>    </span><span>if</span><span> (</span><span>f</span><span>.</span><span>den</span><span>() </span><span>==</span><span> </span><span>1</span><span>) </span><span>return</span><span> </span><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>f</span><span>.</span><span>num</span><span>();</span></div></div><div><div><div>55</div></div><div><span>    </span><span>return</span><span> </span><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>f</span><span>.</span><span>num</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"/"</span><span> </span><span>&lt;&lt;</span><span> </span><span>f</span><span>.</span><span>den</span><span>();</span></div></div><div><div><div>56</div></div><div><span>}</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>59</div></div><div><span>    </span><span>Fraction</span><span> </span><span>a</span><span>(</span><span>1</span><span>, </span><span>2</span><span>), </span><span>b</span><span>(</span><span>3</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>60</div></div><div>
</div></div><div><div><div>61</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>" + "</span><span> </span><span>&lt;&lt;</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>" = "</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 5/4</span></div></div><div><div><div>62</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>" * "</span><span> </span><span>&lt;&lt;</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>" = "</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>*</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 3/8</span></div></div><div><div><div>63</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>" - "</span><span> </span><span>&lt;&lt;</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>" = "</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>-</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // -1/4</span></div></div><div><div><div>64</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>a</span><span> </span><span>&lt;</span><span> </span><span>b</span><span> </span><span>?</span><span> </span><span>"a&lt;b"</span><span> </span><span>:</span><span> </span><span>"a&gt;=b"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>65</div></div><div>
</div></div><div><div><div>66</div></div><div><span>    </span><span>Fraction</span><span> </span><span>c</span><span>(</span><span>2</span><span>, </span><span>4</span><span>);</span><span>        // 自动约分成 1/2</span></div></div><div><div><div>67</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>  // 1/2</span></div></div><div><div><div>68</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>省力技巧（C++20 <code>&lt;=&gt;</code>）</strong>：三路比较一行顶六行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// C++20：自动生成 == != &lt; &lt;= &gt; &gt;=</span></div></div><div><div><div>2</div></div><div><span>auto</span><span> </span><span>operator</span><span>&lt;=&gt;(</span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span>) </span><span>const</span><span> </span><span>=</span><span> </span><span>default</span><span>;</span><span>   // 需成员逐一可比较</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、流运算符 &lt;&lt; 与 &gt;&gt;<a href="#三流运算符--与-"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// &lt;&lt; 必须是非成员（左操作数是 ostream，不是我们的类）</span></div></div><div><div><div>2</div></div><div><span>std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span><span> </span><span>os</span><span>, </span></span><span>const</span><span> </span><span>Fraction</span><span>&amp;</span><span><span> </span><span>f</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> </span><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>f</span><span>.</span><span>num</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"/"</span><span> </span><span>&lt;&lt;</span><span> </span><span>f</span><span>.</span><span>den</span><span>();</span><span>   // 返回 os 引用 → 支持链式</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// &gt;&gt; 输入版</span></div></div><div><div><div>7</div></div><div><span>std::</span><span>istream</span><span>&amp;</span><span> </span><span>operator</span><span>&gt;&gt;(std::</span><span>istream</span><span>&amp;</span><span><span> </span><span>is</span><span>, </span></span><span>Fraction</span><span>&amp;</span><span><span> </span><span>f</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>long</span><span> </span><span>n</span><span>, </span><span>d</span><span>;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>char</span><span> </span><span>slash</span><span>;</span></div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span> (</span><span>is</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span> </span><span>&gt;&gt;</span><span> </span><span>slash</span><span> </span><span>&gt;&gt;</span><span> </span><span>d</span><span> </span><span>&amp;&amp;</span><span> </span><span>slash</span><span> </span><span>==</span><span> </span><span>'/'</span><span>)</span></div></div><div><div><div>11</div></div><div><span>        </span><span>f</span><span> </span><span>=</span><span> </span><span>Fraction</span><span>(</span><span>n</span><span>, </span><span>d</span><span>);</span><span>                   // 输入合法才更新</span></div></div><div><div><div>12</div></div><div><span>    </span><span>else</span></div></div><div><div><div>13</div></div><div><span>        </span><span>is</span><span>.</span><span>setstate</span><span>(std::ios::</span><span>failbit</span><span>);</span><span>       // 标记失败</span></div></div><div><div><div>14</div></div><div><span>    </span><span>return</span><span> </span><span>is</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div><span>// 用法：std::cout &lt;&lt; a &lt;&lt; " " &lt;&lt; b &lt;&lt; "\n";  链式全靠返回 os</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>四、下标、调用与类型转换运算符<a href="#四下标调用与类型转换运算符"><span>#</span></a></h2><section><h3>operator[]：让对象像数组<a href="#operator让对象像数组"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>IntArray</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>data_</span><span>;</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>explicit</span><span> </span><span>IntArray</span><span>(</span><span>size_t</span><span><span> </span><span>n</span><span>) : </span></span><span>data_</span><span>(</span><span>n</span><span>) {}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>int&amp;</span><span> </span><span>operator</span><span>[](</span><span>size_t</span><span><span> </span><span>i</span><span>) { </span></span><span>return</span><span> </span><span>data_</span><span>.</span><span>at</span><span>(</span><span>i</span><span>); }</span><span>          // 可写版本</span></div></div><div><div><div>7</div></div><div><span>    </span><span>const</span><span> </span><span>int&amp;</span><span> </span><span>operator</span><span>[](</span><span>size_t</span><span> </span><span>i</span><span>) </span><span>const</span><span> { </span><span>return</span><span> </span><span>data_</span><span>.</span><span>at</span><span>(</span><span>i</span><span>); }</span><span>  // 只读版本</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>size_t</span><span> </span><span>size</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>data_</span><span>.</span><span>size</span><span>(); }</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>IntArray</span><span> </span><span>arr</span><span>(</span><span>5</span><span>);</span></div></div><div><div><div>13</div></div><div><span>arr</span><span>[</span><span>0</span><span>] </span><span>=</span><span> </span><span>42</span><span>;</span><span>                  // 调可写版</span></div></div><div><div><div>14</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>arr</span><span>[</span><span>0</span><span>];</span><span>          // 调只读版（const 场景）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>operator()：仿函数（函数对象）<a href="#operator仿函数函数对象"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Multiplier</span><span> {</span><span>                    // "行为像函数的对象"</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> </span><span>factor_</span><span>;</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>explicit</span><span> </span><span>Multiplier</span><span>(</span><span>int</span><span><span> </span><span>f</span><span>) : </span></span><span>factor_</span><span>(</span><span>f</span><span>) {}</span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> </span><span>operator</span><span>()(</span><span>int</span><span><span> </span><span>x</span><span>) </span></span><span>const</span><span> {</span><span>     // 重载调用运算符</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>factor_</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>Multiplier</span><span> </span><span>triple</span><span>(</span><span>3</span><span>);</span></div></div><div><div><div>11</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>triple</span><span>(</span><span>10</span><span>);</span><span>              // 30——像调用函数一样使用对象</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// STL 中 lambda 本质就是编译器生成的仿函数类！</span></div></div><div><div><div>14</div></div><div><span>auto</span><span> </span><span>quadruple</span><span> </span><span>=</span><span> [](</span><span>int</span><span><span> </span><span>x</span><span>) { </span></span><span>return</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>4</span><span>; };</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>类型转换运算符<a href="#类型转换运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Fraction</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>// ...</span></div></div><div><div><div>3</div></div><div><span>public:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>explicit</span><span> </span><span>operator</span><span> double() </span><span>const</span><span> {</span><span>      // 显式转 double</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span> </span><span>double</span><span>(</span><span>num_</span><span>) </span><span>/</span><span> </span><span>den_</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>Fraction</span><span> </span><span>f</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>10</div></div><div><span>double</span><span> </span><span>d</span><span> </span><span>=</span><span> </span><span><span>static_cast</span><span>&lt;double&gt;</span></span><span>(</span><span>f</span><span>);</span><span>   // ✓ 显式转换</span></div></div><div><div><div>11</div></div><div><span>// double e = f;                    // ❌ explicit 禁止隐式转换（防意外）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、友元（friend）<a href="#五友元friend"><span>#</span></a></h2><section><h3>问题：非成员函数想访问私有成员<a href="#问题非成员函数想访问私有成员"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>BankAccount</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>friend</span><span> std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span>, </span><span>const</span><span> </span><span>BankAccount</span><span>&amp;</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>// ↑ 声明这个函数是"朋友"：允许它访问我的 private</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>private:</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>owner_</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>double</span><span> </span><span>balance_</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>public:</span></div></div><div><div><div>10</div></div><div><span>    </span><span>BankAccount</span><span>(std::</span><span>string</span><span><span> </span><span>o</span><span>, </span></span><span>double</span><span><span> </span><span>b</span><span>) : </span></span><span>owner_</span><span><span>(</span><span>std</span><span>::</span></span><span>move</span><span>(</span><span>o</span><span>)), </span><span>balance_</span><span>(</span><span>b</span><span>) {}</span></div></div><div><div><div>11</div></div><div><span>};</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 友元函数不是成员函数，但能访问私有成员</span></div></div><div><div><div>14</div></div><div><span>std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span><span> </span><span>os</span><span>, </span></span><span>const</span><span> </span><span>BankAccount</span><span>&amp;</span><span><span> </span><span>acc</span><span>) {</span></span></div></div><div><div><div>15</div></div><div><span>    </span><span>return</span><span> </span><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>acc</span><span>.</span><span>owner_</span><span> </span><span>&lt;&lt;</span><span> </span><span>": ¥"</span><span> </span><span>&lt;&lt;</span><span> </span><span>acc</span><span>.</span><span>balance_</span><span>;</span><span>   // ✓ 访问 private</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>BankAccount</span><span> </span><span>a</span><span>(</span><span>"小明"</span><span>, </span><span>100.5</span><span>);</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 小明: ¥100.5</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>友元类与要点<a href="#友元类与要点"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Matrix</span><span>;</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>MatrixIterator</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>friend</span><span> </span><span>class</span><span> </span><span>Matrix</span><span>;</span><span>      // Matrix 的所有成员函数都可访问我的私有</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>// ...</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>友元三原则</strong>：friend 是”授予”而非”索取”（类自己声明谁是我朋友）；友元破坏封装，能不用就不用；<strong>合法场景</strong>：运算符重载、紧密协作的类对（Container 与它的 Iterator）。</p><p><strong>友元不被继承、不是双向的、不传递</strong>。</p></section></section>
<section><h2>六、何时不该重载<a href="#六何时不该重载"><span>#</span></a></h2>

<table><thead><tr><th>场景</th><th>建议</th></tr></thead><tbody><tr><td>数学类型（向量/分数/矩阵/复数）</td><td>✅ 重载 + - * /，天然合适</td></tr><tr><td>逻辑比较（排序、去重需要）</td><td>✅ <code>&lt;</code> <code>==</code>（配 STL 容器）</td></tr><tr><td>输出调试</td><td>✅ <code>&lt;&lt;</code></td></tr><tr><td><code>&amp;&amp;</code> `</td><td></td></tr><tr><td>逗号 <code>，</code>、取地址 <code>&amp;</code></td><td>❌ 语义迷惑，别碰</td></tr><tr><td>为了少打字把 <code>+</code> 当”追加”用于文件/网络</td><td>⚠ 语义存疑，用命名方法 <code>append</code> 更清晰</td></tr></tbody></table></section>
<section><h2>七、实战：二维向量 Vector2D 完整版<a href="#七实战二维向量-vector2d-完整版"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;cmath&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>class</span><span> </span><span>Vec2</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>double</span><span> </span><span>x_</span><span>, </span><span>y_</span><span>;</span></div></div><div><div><div>6</div></div><div><span>public:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Vec2</span><span>(</span><span>double</span><span><span> </span><span>x</span><span> </span></span><span>=</span><span> </span><span>0</span><span>, </span><span>double</span><span><span> </span><span>y</span><span> </span></span><span>=</span><span> </span><span>0</span><span>) : </span><span>x_</span><span>(</span><span>x</span><span>), </span><span>y_</span><span>(</span><span>y</span><span>) {}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>Vec2</span><span> </span><span>operator</span><span>+(</span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> { </span><span>return</span><span> {</span><span>x_</span><span> </span><span>+</span><span> </span><span>r</span><span>.</span><span>x_</span><span>, </span><span>y_</span><span> </span><span>+</span><span> </span><span>r</span><span>.</span><span>y_</span><span>}; }</span></div></div><div><div><div>10</div></div><div><span>    </span><span>Vec2</span><span> </span><span>operator</span><span>-(</span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> { </span><span>return</span><span> {</span><span>x_</span><span> </span><span>-</span><span> </span><span>r</span><span>.</span><span>x_</span><span>, </span><span>y_</span><span> </span><span>-</span><span> </span><span>r</span><span>.</span><span>y_</span><span>}; }</span></div></div><div><div><div>11</div></div><div><span>    </span><span>Vec2</span><span> </span><span>operator</span><span>*(</span><span>double</span><span><span> </span><span>k</span><span>) </span></span><span>const</span><span> { </span><span>return</span><span> {</span><span>x_</span><span> </span><span>*</span><span> </span><span>k</span><span>, </span><span>y_</span><span> </span><span>*</span><span> </span><span>k</span><span>}; }</span><span>        // 数乘</span></div></div><div><div><div>12</div></div><div><span>    </span><span>Vec2</span><span> </span><span>operator</span><span>-() </span><span>const</span><span> { </span><span>return</span><span> {</span><span>-</span><span>x_</span><span>, </span><span>-</span><span>y_</span><span>}; }</span><span>                       // 取负</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>bool</span><span> </span><span>operator</span><span>==(</span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> { </span><span>return</span><span> </span><span>x_</span><span>==</span><span>r</span><span>.</span><span>x_</span><span> </span><span>&amp;&amp;</span><span> </span><span>y_</span><span>==</span><span>r</span><span>.</span><span>y_</span><span>; }</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>double</span><span> </span><span>dot</span><span>(</span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>r</span><span>) </span></span><span>const</span><span> { </span><span>return</span><span> </span><span>x_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>x_</span><span> </span><span>+</span><span> </span><span>y_</span><span> </span><span>*</span><span> </span><span>r</span><span>.</span><span>y_</span><span>; }</span></div></div><div><div><div>17</div></div><div><span>    </span><span>double</span><span> </span><span>length</span><span>() </span><span>const</span><span> { </span><span>return</span><span> std::</span><span>sqrt</span><span>(</span><span>dot</span><span>(</span><span>*</span><span>this</span><span>)); }</span><span>             // 复用 dot</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>    </span><span>double&amp;</span><span> </span><span>operator</span><span>[](</span><span>size_t</span><span><span> </span><span>i</span><span>) { </span></span><span>return</span><span> </span><span>i</span><span> </span><span>==</span><span> </span><span>0</span><span> </span><span>?</span><span> </span><span>x_</span><span> </span><span>:</span><span> </span><span>y_</span><span>; }</span><span>           // v[0]/v[1]</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>friend</span><span> std::</span><span>ostream</span><span>&amp;</span><span> </span><span>operator</span><span>&lt;&lt;(std::</span><span>ostream</span><span>&amp;</span><span><span> </span><span>os</span><span>, </span></span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>v</span><span>) {</span></span></div></div><div><div><div>22</div></div><div><span>        </span><span>return</span><span> </span><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>"("</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>.</span><span>x_</span><span> </span><span>&lt;&lt;</span><span> </span><span>", "</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>.</span><span>y_</span><span> </span><span>&lt;&lt;</span><span> </span><span>")"</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>};</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>Vec2</span><span> </span><span>operator</span><span>*(</span><span>double</span><span><span> </span><span>k</span><span>, </span></span><span>const</span><span> </span><span>Vec2</span><span>&amp;</span><span><span> </span><span>v</span><span>) { </span></span><span>return</span><span> </span><span>v</span><span> </span><span>*</span><span> </span><span>k</span><span>; }</span><span>   // 3*v 也成立</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>29</div></div><div><span>    </span><span>Vec2</span><span> </span><span>a</span><span>(</span><span>1</span><span>, </span><span>2</span><span>), </span><span>b</span><span>(</span><span>3</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"a="</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>" b="</span><span> </span><span>&lt;&lt;</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"a+b="</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>       // (4, 6)</span></div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"a·b="</span><span> </span><span>&lt;&lt;</span><span> </span><span>a</span><span>.</span><span>dot</span><span>(</span><span>b</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>    // 11</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"|b|="</span><span> </span><span>&lt;&lt;</span><span> </span><span>b</span><span>.</span><span>length</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>  // 5</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"3a="</span><span> </span><span>&lt;&lt;</span><span> </span><span>3</span><span> </span><span>*</span><span> </span><span>a</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>        // (3, 6)</span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>    </span><span>Vec2</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span> </span><span>*</span><span> </span><span>2</span><span>;</span><span>                          // 数学式表达式</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>[</span><span>0</span><span>] </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>[</span><span>1</span><span>] </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>   // 7,10</span></div></div><div><div><div>39</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>给 Fraction 补全 <code>&gt;= &lt;= &gt; !=</code>（用 <code>&lt;</code> 和 <code>==</code> 组合实现）</li>
<li>实现 <code>Temperature</code> 类：内部存摄氏，<code>operator+</code>、转华氏方法、<code>&lt;&lt;</code> 输出两种温标</li>
<li>实现 <code>Str</code> 简易字符串类：<code>operator+</code> 拼接、<code>operator[]</code> 访问、<code>operator==</code> 比较</li>
<li>写 <code>Accumulator</code> 仿函数：每次 <code>()</code> 调用累加并返回累计值（对比第六篇闭包计数器）</li>
<li>（思考）为什么 <code>operator&lt;&lt;</code> 不能是成员函数？为什么 <code>operator+=</code> 通常是成员而 <code>operator+</code> 常是非成员？</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>可重载绝大多数运算符，但语义必须符合直觉；<code>&amp;&amp;</code>/<code>||</code> 别重载（失短路）</li>
<li>修改自身用成员（<code>+= = [] ()</code>），对称与流用非成员（<code>+ == &lt;&lt; &gt;&gt;</code>）</li>
<li>算术返回新值 const，复合赋值返回 <code>*this&amp;</code></li>
<li><code>&lt;&lt;</code> 返回 ostream 引用支撑链式；C++20 <code>&lt;=&gt;</code> 一行生成全套比较</li>
<li>friend 授予外部访问私有的权限，仅用于运算符/姊妹类</li>
<li>仿函数 <code>operator()</code> 是 lambda 的本质</li>
</ul><p><strong>下一篇</strong>：STL 标准模板库总览——容器、迭代器与算法的完整武器库。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。Fraction 与 Vec2 是面试白板题常客，建议默写一遍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-11/</id>
      <title type="text">C++ 入门教程（十一）：STL 标准模板库</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-11/"/>
      <summary type="text">系统遍历 STL 三大件：容器（vector/deque/list/map/set/unordered）选型对比、迭代器体系与常用算法（sort/find/count/accumulate/for_each/remove），附词频统计与成绩系统综合案例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p><strong>STL（Standard Template Library）</strong> 是 C++ 自带的”兵器库”：6+ 种容器、几十个算法、通用迭代器粘合两者。学完本篇，你写 C++ 的效率会翻倍——不再手写链表、排序、查找，组合现成部件即可。</p></section>
<section><h2>一、STL 全景图<a href="#一stl-全景图"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>STL 三大件：</span></div></div><div><div><div>2</div></div><div><span>├── 容器（Containers）：存数据    vector / list / map / set ...</span></div></div><div><div><div>3</div></div><div><span>├── 迭代器（Iterators）：胶水     统一遍历所有容器的方式</span></div></div><div><div><div>4</div></div><div><span>└── 算法（Algorithms）：处理数据  sort / find / count / accumulate ...</span></div></div><div><div><div>5</div></div><div><span>+ 仿函数 &amp; lambda：算法的"策略参数"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>头文件速记：容器各有头（<code>&lt;vector&gt;</code> <code>&lt;map&gt;</code>…），算法统一 <code>&lt;algorithm&gt;</code>，数值算法 <code>&lt;numeric&gt;</code>。</p></section>
<section><h2>二、顺序容器<a href="#二顺序容器"><span>#</span></a></h2><section><h3>vector（复习+补强）<a href="#vector复习补强"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v</span><span>{</span><span>3</span><span>, </span><span>1</span><span>, </span><span>4</span><span>};</span></div></div><div><div><div>4</div></div><div><span>v</span><span>.</span><span>push_back</span><span>(</span><span>5</span><span>);</span></div></div><div><div><div>5</div></div><div><span>v</span><span>.</span><span>reserve</span><span>(</span><span>100</span><span>);</span><span>            // 预留容量，避免反复扩容拷贝</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>.</span><span>capacity</span><span>() </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>v</span><span>.</span><span>size</span><span>();</span><span>   // 100 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>deque：双端队列<a href="#deque双端队列"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;deque&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>deque</span><span>&lt;</span><span>int</span><span>&gt; </span><span>dq</span><span>{</span><span>2</span><span>, </span><span>3</span><span>};</span></div></div><div><div><div>4</div></div><div><span>dq</span><span>.</span><span>push_front</span><span>(</span><span>1</span><span>);</span><span>      // 头部 O(1)！</span></div></div><div><div><div>5</div></div><div><span>dq</span><span>.</span><span>push_back</span><span>(</span><span>4</span><span>);</span><span>       // {1,2,3,4}</span></div></div><div><div><div>6</div></div><div><span>dq</span><span>.</span><span>pop_front</span><span>();</span><span>        // {2,3,4}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>vs vector：头插头删 O(1)，但内存不连续（缓存稍差）。需要双端操作选它。</p></section><section><h3>list：双向链表<a href="#list双向链表"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;list&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>list</span><span>&lt;</span><span>int</span><span>&gt; </span><span>lst</span><span>{</span><span>1</span><span>, </span><span>2</span><span>, </span><span>4</span><span>};</span></div></div><div><div><div>4</div></div><div><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> std::</span><span>next</span><span>(</span><span>lst</span><span>.</span><span>begin</span><span>());</span><span>      // 指向 2</span></div></div><div><div><div>5</div></div><div><span>lst</span><span>.</span><span>insert</span><span>(</span><span>it</span><span>, </span><span>3</span><span>);</span><span>                     // {1,2→3,4} 任意位置 O(1)</span></div></div><div><div><div>6</div></div><div><span>lst</span><span>.</span><span>remove</span><span>(</span><span>2</span><span>);</span><span>                         // 按值删</span></div></div><div><div><div>7</div></div><div><span>lst</span><span>.</span><span>sort</span><span>();</span><span>                            // list 自带 sort（std::sort 不支持它）</span></div></div><div><div><div>8</div></div><div><span>lst</span><span>.</span><span>splice</span><span>(</span><span>lst</span><span>.</span><span>end</span><span>(), </span><span>another_list</span><span>);</span><span>   // O(1) 拼接另一链表</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>list 的取舍</strong>：中间插删 O(1) 但不支持随机访问 <code>[i]</code>（要 O(n) 走链）、缓存不友好。<strong>90% 场景 vector 更快</strong>——包括”中间插删”（vector 移动内存飞快），实测再说。</p></section><section><h3>顺序容器对比<a href="#顺序容器对比"><span>#</span></a></h3>

<table><thead><tr><th></th><th>vector</th><th>deque</th><th>list</th></tr></thead><tbody><tr><td>随机访问</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></tr><tr><td>中间插删</td><td>O(n)</td><td>O(n)</td><td><strong>O(1)</strong>（有迭代器）</td></tr><tr><td>内存</td><td>连续</td><td>分块</td><td>节点散布</td></tr><tr><td>默认选择</td><td>⭐</td><td>双端需求</td><td>特殊链表需求</td></tr></tbody></table></section></section>
<section><h2>三、关联容器<a href="#三关联容器"><span>#</span></a></h2><section><h3>map：有序键值对（红黑树）<a href="#map有序键值对红黑树"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;map&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>map</span><span>&lt;</span><span>std::</span><span>string</span><span>, </span><span>int&gt;</span><span> </span><span>ages</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 插入三种方式</span></div></div><div><div><div>7</div></div><div><span>ages</span><span>[</span><span>"小明"</span><span>] </span><span>=</span><span> </span><span>18</span><span>;</span><span>                          // 不存在则插入，存在则覆盖</span></div></div><div><div><div>8</div></div><div><span>ages</span><span>.</span><span>insert</span><span>({</span><span>"小红"</span><span>, </span><span>17</span><span>});</span></div></div><div><div><div>9</div></div><div><span>ages</span><span>.</span><span>emplace</span><span>(</span><span>"小刚"</span><span>, </span><span>19</span><span>);</span><span>                    // 原地构造（推荐）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 安全访问：at 越界抛异常，[] 越界会"悄悄创建"！</span></div></div><div><div><div>12</div></div><div><span>try</span><span> { </span><span>ages</span><span>.</span><span>at</span><span>(</span><span>"不存在"</span><span>); } </span><span>catch</span><span> (</span><span>const</span><span> std::</span><span>out_of_range</span><span>&amp;</span><span>) { }</span></div></div><div><div><div>13</div></div><div><span>int</span><span> </span><span>cnt</span><span> </span><span>=</span><span> </span><span>ages</span><span>.</span><span>count</span><span>(</span><span>"小明"</span><span>);</span><span>                // 0 或 1</span></div></div><div><div><div>14</div></div><div><span>// ages["不存在的键"];                       // ⚠ 危险：会插入默认值！</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// 遍历（按键自动排序）</span></div></div><div><div><div>17</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>name</span><span>, </span><span>age</span><span>] : </span><span>ages</span><span>)</span><span>        // 结构化绑定</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>age</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>// 查找</span></div></div><div><div><div>21</div></div><div><span>if</span><span> (</span><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> </span><span>ages</span><span>.</span><span>find</span><span>(</span><span>"小明"</span><span>); </span><span>it</span><span> </span><span>!=</span><span> </span><span>ages</span><span>.</span><span>end</span><span>())</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>it</span><span>-&gt;</span><span>second</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div></div><div>Warning</div></div><div><p><code>map::operator[]</code> 对不存在的键<strong>会插入默认值</strong>——只读查询场景永远用 <code>find</code> 或 <code>count</code>，这是 map 的第一大坑。</p></div></div></section><section><h3>set：有序去重集合<a href="#set有序去重集合"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;set&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>set</span><span>&lt;</span><span>int</span><span>&gt; </span><span>s</span><span>{</span><span>3</span><span>, </span><span>1</span><span>, </span><span>4</span><span>, </span><span>1</span><span>, </span><span>5</span><span>};</span><span>         // {1,3,4,5} 自动去重排序</span></div></div><div><div><div>4</div></div><div><span>s</span><span>.</span><span>insert</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>5</div></div><div><span>s</span><span>.</span><span>erase</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>if</span><span> (</span><span>s</span><span>.</span><span>count</span><span>(</span><span>3</span><span>)) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"3 在集合</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>8</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>s</span><span>.</span><span>size</span><span>();</span><span>                   // 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>unordered_map / unordered_set（哈希表）<a href="#unordered_map--unordered_set哈希表"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;unordered_map&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>std::</span><span>unordered_map</span><span>&lt;</span><span>std::</span><span>string</span><span>, </span><span>int&gt;</span><span> </span><span>fast</span><span>;</span></div></div><div><div><div>4</div></div><div><span>fast</span><span>[</span><span>"apple"</span><span>] </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>5</div></div><div><span>// 接口与 map 完全一致！区别在实现：</span></div></div><div><div><div>6</div></div><div><span>// map         红黑树   查找 O(log n)   键有序遍历</span></div></div><div><div><div>7</div></div><div><span>// unordered   哈希表   查找 O(1) 均摊  遍历无序</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>选型</strong>：需要有序遍历/范围查询用 map/set；纯查找用 unordered（更快，日常默认）。</p></section><section><h3>multimap / multiset<a href="#multimap--multiset"><span>#</span></a></h3><p>允许重复键：<code>std::multimap&lt;std::string, int&gt;</code> 一个键多个值（如一个学生多门课成绩）。</p></section></section>
<section><h2>四、迭代器<a href="#四迭代器"><span>#</span></a></h2><section><h3>统一的遍历语法<a href="#统一的遍历语法"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v</span><span>{</span><span>1</span><span>,</span><span>2</span><span>,</span><span>3</span><span>};</span></div></div><div><div><div>2</div></div><div><span>std::</span><span>map</span><span>&lt;std::</span><span>string</span><span>,</span><span>int</span><span>&gt; </span><span>m</span><span>{{</span><span>"a"</span><span>,</span><span>1</span><span>}};</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>for</span><span> (</span><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> </span><span>v</span><span>.</span><span>begin</span><span>(); </span><span>it</span><span> </span><span>!=</span><span> </span><span>v</span><span>.</span><span>end</span><span>(); </span><span>++</span><span>it</span><span>)</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>*</span><span>it</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>k</span><span>, </span><span>val</span><span>] : </span><span>m</span><span>)</span><span>      // 范围 for 底层就是迭代器</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>k</span><span> </span><span>&lt;&lt;</span><span> </span><span>val</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>常用操作<a href="#常用操作"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v</span><span>{</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>, </span><span>50</span><span>};</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> </span><span>v</span><span>.</span><span>begin</span><span>();</span></div></div><div><div><div>4</div></div><div><span><span>std</span><span>::</span></span><span>advance</span><span>(</span><span>it</span><span>, </span><span>2</span><span>);</span><span>                    // 前进 2 → 指向 30</span></div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>d</span><span> </span><span>=</span><span> std::</span><span>distance</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>it</span><span>);</span><span>   // 2</span></div></div><div><div><div>6</div></div><div><span>auto</span><span> </span><span>it2</span><span> </span><span>=</span><span> std::</span><span>next</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>());</span><span>        // 第二个（原迭代器不动）</span></div></div><div><div><div>7</div></div><div><span>auto</span><span> </span><span>it3</span><span> </span><span>=</span><span> std::</span><span>prev</span><span>(</span><span>v</span><span>.</span><span>end</span><span>());</span><span>          // 最后一个</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// ⚠ 迭代器失效头号场景：边遍历边删</span></div></div><div><div><div>10</div></div><div><span>// for (auto it = v.begin(); it != v.end(); ++it)</span></div></div><div><div><div>11</div></div><div><span>//     if (*it % 2) v.erase(it);        // ❌ erase 后 it 失效！</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// ✅ 正确姿势：用 erase 的返回值</span></div></div><div><div><div>14</div></div><div><span>for</span><span> (</span><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> </span><span>v</span><span>.</span><span>begin</span><span>(); </span><span>it</span><span> </span><span>!=</span><span> </span><span>v</span><span>.</span><span>end</span><span>(); )</span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span> (</span><span>*</span><span>it</span><span> </span><span>%</span><span> </span><span>2</span><span> </span><span>!=</span><span> </span><span>0</span><span>) </span><span>it</span><span> </span><span>=</span><span> </span><span>v</span><span>.</span><span>erase</span><span>(</span><span>it</span><span>);</span><span>     // erase 返回下一个有效迭代器</span></div></div><div><div><div>16</div></div><div><span>    </span><span>else</span><span> </span><span>++</span><span>it</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>五、算法库（ / ）<a href="#五算法库--"><span>#</span></a></h2><section><h3>查找与统计<a href="#查找与统计"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;numeric&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>v</span><span>{</span><span>3</span><span>, </span><span>1</span><span>, </span><span>4</span><span>, </span><span>1</span><span>, </span><span>5</span><span>, </span><span>9</span><span>, </span><span>2</span><span>, </span><span>6</span><span>};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>std</span><span>::</span></span><span>find</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>5</span><span>);</span><span>            // 找值，end()=没找到</span></div></div><div><div><div>7</div></div><div><span><span>std</span><span>::</span></span><span>count</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>1</span><span>);</span><span>           // 2</span></div></div><div><div><div>8</div></div><div><span><span>std</span><span>::</span></span><span>accumulate</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>0</span><span>);</span><span>      // 31 求和（&lt;numeric&gt;）</span></div></div><div><div><div>9</div></div><div><span><span>std</span><span>::</span></span><span>max_element</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span><span>        // 指向 9 的迭代器</span></div></div><div><div><div>10</div></div><div><span><span>std</span><span>::</span></span><span>minmax_element</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span><span>     // pair&lt;min_it, max_it&gt;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 条件版</span></div></div><div><div><div>13</div></div><div><span>auto</span><span> </span><span>cnt_even</span><span> </span><span>=</span><span> std::</span><span>count_if</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>14</div></div><div><span><span>                              </span></span><span>[](</span><span>int</span><span><span> </span><span>x</span><span>){ </span></span><span>return</span><span> </span><span>x</span><span> </span><span>%</span><span> </span><span>2</span><span> </span><span>==</span><span> </span><span>0</span><span>; });</span></div></div><div><div><div>15</div></div><div><span>auto</span><span> </span><span>it_big</span><span> </span><span>=</span><span> std::</span><span>find_if</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>16</div></div><div><span><span>                           </span></span><span>[](</span><span>int</span><span><span> </span><span>x</span><span>){ </span></span><span>return</span><span> </span><span>x</span><span> </span><span>&gt;</span><span> </span><span>5</span><span>; });</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>排序与变换<a href="#排序与变换"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span><span>                          // 升序</span></div></div><div><div><div>2</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), std::</span><span>greater</span><span>&lt;</span><span>int</span><span>&gt;());</span><span>     // 降序</span></div></div><div><div><div>3</div></div><div><span><span>std</span><span>::</span></span><span>stable_sort</span><span>(...);</span><span>                                  // 稳定（相等保持原序）</span></div></div><div><div><div>4</div></div><div><span><span>std</span><span>::</span></span><span>partial_sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>begin</span><span>()</span><span>+</span><span>3</span><span>, </span><span>v</span><span>.</span><span>end</span><span>());</span><span>     // 只排前 3</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>std</span><span>::</span></span><span>reverse</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>7</div></div><div><span><span>std</span><span>::</span></span><span>transform</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>v</span><span>.</span><span>begin</span><span>(),</span><span>           // 原地变换</span></div></div><div><div><div>8</div></div><div><span><span>               </span></span><span>[](</span><span>int</span><span><span> </span><span>x</span><span>){ </span></span><span>return</span><span> </span><span>x</span><span> </span><span>*</span><span> </span><span>x</span><span>; });</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>std::</span><span>vector</span><span>&lt;</span><span>int</span><span>&gt; </span><span>dst</span><span>(</span><span>v</span><span>.</span><span>size</span><span>());</span></div></div><div><div><div>11</div></div><div><span><span>std</span><span>::</span></span><span>copy</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>dst</span><span>.</span><span>begin</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>经典三连：remove + erase 真删除<a href="#经典三连remove--erase-真删除"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// remove 只把"要删的"挪到末尾，返回新逻辑末尾——容器 size 不变！</span></div></div><div><div><div>2</div></div><div><span>auto</span><span> </span><span>new_end</span><span> </span><span>=</span><span> std::</span><span>remove_if</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>3</div></div><div><span><span>                              </span></span><span>[](</span><span>int</span><span><span> </span><span>x</span><span>){ </span></span><span>return</span><span> </span><span>x</span><span> </span><span>&lt;</span><span> </span><span>3</span><span>; });</span></div></div><div><div><div>4</div></div><div><span>v</span><span>.</span><span>erase</span><span>(</span><span>new_end</span><span>, </span><span>v</span><span>.</span><span>end</span><span>());</span><span>      // 真正删除（erase-remove 惯用法）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>二分查找（需先有序）<a href="#二分查找需先有序"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>std</span><span>::</span></span><span>sort</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>2</div></div><div><span>bool</span><span> </span><span>found</span><span> </span><span>=</span><span> std::</span><span>binary_search</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>5</span><span>);</span><span>   // 是否存在</span></div></div><div><div><div>3</div></div><div><span>auto</span><span> </span><span>lb</span><span> </span><span>=</span><span> std::</span><span>lower_bound</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>5</span><span>);</span><span>        // 第一个 &gt;= 5</span></div></div><div><div><div>4</div></div><div><span>auto</span><span> </span><span>ub</span><span> </span><span>=</span><span> std::</span><span>upper_bound</span><span>(</span><span>v</span><span>.</span><span>begin</span><span>(), </span><span>v</span><span>.</span><span>end</span><span>(), </span><span>5</span><span>);</span><span>        // 第一个 &gt; 5</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>ub</span><span> </span><span>-</span><span> </span><span>lb</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>                             // 值 5 的个数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、综合案例<a href="#六综合案例"><span>#</span></a></h2><section><h3>1. 词频统计（map 的主场）<a href="#1-词频统计map-的主场"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;map&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;sstream&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>5</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>text</span><span> </span><span>=</span><span> </span><span>"the quick the lazy the dog and the end"</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>std::</span><span>map</span><span>&lt;std::</span><span>string</span><span>, </span><span>int</span><span>&gt; </span><span>freq</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>istringstream</span><span> </span><span>ss</span><span>(</span><span>text</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>word</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>while</span><span> (</span><span>ss</span><span> </span><span>&gt;&gt;</span><span> </span><span>word</span><span>) </span><span>++</span><span>freq</span><span>[</span><span>word</span><span>];</span><span>        // 一行完成计数！</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>// 按次数降序输出：搬进 vector 排序</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;std::</span><span>pair</span><span>&lt;std::</span><span>string</span><span>, </span><span>int</span><span>&gt;&gt; </span><span>items</span><span>(</span><span>freq</span><span>.</span><span>begin</span><span>(), </span><span>freq</span><span>.</span><span>end</span><span>());</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>std::</span><span>sort</span><span>(</span><span>items</span><span>.</span><span>begin</span><span>(), </span><span>items</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>18</div></div><div><span><span>              </span></span><span>[](</span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>auto&amp;</span><span><span> </span><span>b</span><span>){ </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>second</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>.</span><span>second</span><span>; });</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>w</span><span>, </span><span>c</span><span>] : </span><span>items</span><span>)</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>w</span><span> </span><span>&lt;&lt;</span><span> </span><span>": "</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>2. 学生成绩系统（多容器协作）<a href="#2-学生成绩系统多容器协作"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>struct</span><span> </span><span>Record</span><span> { std::</span><span>string</span><span> </span><span>name</span><span>; </span><span>int</span><span> </span><span>score</span><span>; };</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>Record</span><span>&gt; </span><span>records</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>{</span><span>"小明"</span><span>, </span><span>90</span><span>}, {</span><span>"小红"</span><span>, </span><span>85</span><span>}, {</span><span>"小刚"</span><span>, </span><span>92</span><span>}, {</span><span>"小红"</span><span>, </span><span>88</span><span>},</span><span>   // 小红两次</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>// 1. 总分与平均（accumulate + lambda 初始化值注意类型）</span></div></div><div><div><div>9</div></div><div><span>    </span><span>int</span><span> </span><span>total</span><span> </span><span>=</span><span> std::</span><span>accumulate</span><span>(</span><span>records</span><span>.</span><span>begin</span><span>(), </span><span>records</span><span>.</span><span>end</span><span>(), </span><span>0</span><span>,</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>[](</span><span>int</span><span><span> </span><span>sum</span><span>, </span></span><span>const</span><span> </span><span>Record</span><span>&amp;</span><span><span> </span><span>r</span><span>){ </span></span><span>return</span><span> </span><span>sum</span><span> </span><span>+</span><span> </span><span>r</span><span>.</span><span>score</span><span>; });</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"平均 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>total</span><span> </span><span>/</span><span> </span><span>double</span><span>(</span><span>records</span><span>.</span><span>size</span><span>()) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>// 2. 每人最高分（map&lt;string,int&gt;）</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>map</span><span>&lt;std::</span><span>string</span><span>, </span><span>int</span><span>&gt; </span><span>best</span><span>;</span></div></div><div><div><div>15</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>r</span><span> : </span><span>records</span><span>)</span></div></div><div><div><div>16</div></div><div><span>        </span><span>best</span><span>[</span><span>r</span><span>.</span><span>name</span><span>] </span><span>=</span><span> std::</span><span>max</span><span>(</span><span>best</span><span>[</span><span>r</span><span>.</span><span>name</span><span>], </span><span>r</span><span>.</span><span>score</span><span>);</span><span>   // 默认 0 起步</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>// 3. 排名（拷贝+排序，不破坏原序）</span></div></div><div><div><div>19</div></div><div><span>    </span><span>auto</span><span> </span><span>ranked</span><span> </span><span>=</span><span> </span><span>records</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>std::</span><span>sort</span><span>(</span><span>ranked</span><span>.</span><span>begin</span><span>(), </span><span>ranked</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>21</div></div><div><span><span>              </span></span><span>[](</span><span>const</span><span> </span><span>Record</span><span>&amp;</span><span><span> </span><span>a</span><span>, </span></span><span>const</span><span> </span><span>Record</span><span>&amp;</span><span><span> </span><span>b</span><span>){ </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>score</span><span> </span><span>&gt;</span><span> </span><span>b</span><span>.</span><span>score</span><span>; });</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>// 4. 及格人数</span></div></div><div><div><div>24</div></div><div><span>    </span><span>auto</span><span> </span><span>passed</span><span> </span><span>=</span><span> std::</span><span>count_if</span><span>(</span><span>records</span><span>.</span><span>begin</span><span>(), </span><span>records</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>25</div></div><div><span><span>                                </span></span><span>[](</span><span>const</span><span> </span><span>Record</span><span>&amp;</span><span><span> </span><span>r</span><span>){ </span></span><span>return</span><span> </span><span>r</span><span>.</span><span>score</span><span> </span><span>&gt;=</span><span> </span><span>60</span><span>; });</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>七、容器选型决策表<a href="#七容器选型决策表"><span>#</span></a></h2>

<table><thead><tr><th>需求</th><th>容器</th></tr></thead><tbody><tr><td>动态数组（默认）</td><td><code>vector</code></td></tr><tr><td>双端频繁插删</td><td><code>deque</code></td></tr><tr><td>键值查找（默认）</td><td><code>unordered_map</code></td></tr><tr><td>键值 + 有序遍历</td><td><code>map</code></td></tr><tr><td>去重集合（默认）</td><td><code>unordered_set</code></td></tr><tr><td>有序集合/排行</td><td><code>set</code></td></tr><tr><td>一键多值</td><td><code>multimap</code> / <code>unordered_map&lt;K, vector&lt;V&gt;&gt;</code></td></tr><tr><td>优先队列（堆）</td><td><code>priority_queue</code>（进阶了解）</td></tr></tbody></table></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>用 <code>map&lt;char,int&gt;</code> 统计字符串各字符出现次数，输出出现最多的字符</li>
<li>两个小组名单合并去重：<code>vector&lt;string&gt;</code> + <code>sort</code> + <code>unique</code> + <code>erase</code></li>
<li>用 <code>erase-remove</code> 惯用法删除 vector 中所有负数</li>
<li>用 <code>accumulate</code> 计算字符串向量所有元素的总长度</li>
<li>模拟”商品库存”：unordered_map&lt;string,int&gt;，支持进货、售出（减到 0 提示缺货）、按名称排序输出全部</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>顺序容器默认 vector；关联容器默认 unordered 系列；有序需求才 map/set</li>
<li><code>map[]</code> 会插入默认值，只读用 find/count</li>
<li>迭代器是容器与算法的胶水；erase 返回值防迭代器失效</li>
<li>算法库三板斧：sort/count_if/accumulate + find_if/max_element</li>
<li>真删除用 erase-remove 惯用法；二分先排序</li>
<li>组合容器+算法，绝大多数需求无需手写数据结构</li>
</ul><p><strong>下一篇</strong>：异常处理与文件 IO——系列的收官与综合实战。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。STL 的熟练度 = C++ 的日常生产力，练习 5 的库存系统务必完整实现。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/cpp-tutorial-12/</id>
      <title type="text">C++ 入门教程（十二）：异常处理、文件 IO 与综合实战</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/cpp-tutorial-12/"/>
      <summary type="text">系列收官：C++ 异常体系（throw/try/catch、标准异常层级、自定义异常、 noexcept）、文件流读写（ifstream/ofstream/stringstream）、通讯录项目综合实战与系列总结。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>最后两块拼图：<strong>异常处理</strong>（出错不崩）与<strong>文件 IO</strong>（数据持久化），随后用一个综合项目收官全系列——做一个支持增删改查、文件持久化的<strong>通讯录管理系统</strong>。</p></section>
<section><h2>一、C++ 异常处理<a href="#一c-异常处理"><span>#</span></a></h2><section><h3>基本语法<a href="#基本语法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;stdexcept&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>double</span><span> </span><span>safe_divide</span><span>(</span><span>double</span><span><span> </span><span>a</span><span>, </span></span><span>double</span><span><span> </span><span>b</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> (</span><span>b</span><span> </span><span>==</span><span> </span><span>0</span><span>)</span></div></div><div><div><div>6</div></div><div><span>        </span><span>throw</span><span> std::</span><span>invalid_argument</span><span>(</span><span>"除数不能为零"</span><span>);</span><span>   // 抛出异常对象</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>a</span><span> </span><span>/</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>try</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>safe_divide</span><span>(</span><span>10</span><span>, </span><span>2</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>     // 5</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>safe_divide</span><span>(</span><span>1</span><span>, </span><span>0</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>      // 这里抛出</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"永远执行不到</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>    </span><span>catch</span><span> (</span><span>const</span><span> std::</span><span>invalid_argument</span><span>&amp;</span><span> </span><span>e</span><span>) {</span><span>          // 按类型捕获</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"参数错误: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>what</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>    </span><span>catch</span><span> (</span><span>const</span><span> std::</span><span>exception</span><span>&amp;</span><span> </span><span>e</span><span>) {</span><span>                 // 基类兜底（顺序：子类在前！）</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"其他异常: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>what</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>    </span><span>catch</span><span> (...) {</span><span>                                     // 万能兜底</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"未知异常</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>与 Python 的差异</strong>：C++ 用对象抛出（不是字符串）、按<strong>类型</strong>匹配 catch、catch 顺序敏感（子类必须放基类前面）。</p></section><section><h3>标准异常层级（）<a href="#标准异常层级"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::exception                 ← 所有标准异常的基类</span></div></div><div><div><div>2</div></div><div><span>├── logic_error                ← 程序逻辑错误（可预防）</span></div></div><div><div><div>3</div></div><div><span>│   ├── invalid_argument       参数非法</span></div></div><div><div><div>4</div></div><div><span>│   ├── out_of_range           下标越界（vector::at 抛的就是它）</span></div></div><div><div><div>5</div></div><div><span>│   └── length_error           超长</span></div></div><div><div><div>6</div></div><div><span>└── runtime_error              ← 运行期才能发现</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>├── overflow_error         算术上溢</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>├── underflow_error        下溢</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>└── range_error            值域错误</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>另有：bad_alloc（new 失败，&lt;new&gt;）、bad_cast（&lt;typeinfo&gt;）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>自定义异常<a href="#自定义异常"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;stdexcept&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>class</span><span> </span><span>InsufficientFundsError</span><span> : </span><span>public</span><span> std::</span><span>runtime_error</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>double</span><span> </span><span>shortfall_</span><span>;</span></div></div><div><div><div>6</div></div><div><span>public:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>explicit</span><span> </span><span>InsufficientFundsError</span><span>(</span><span>double</span><span><span> </span><span>shortfall</span><span>)</span></span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>: std::</span><span>runtime_error</span><span>(</span><span>"余额不足，还差 "</span><span> </span><span>+</span><span> std::</span><span>to_string</span><span>(</span><span>shortfall</span><span>) </span><span>+</span><span> </span><span>" 元"</span><span>)</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>, </span><span>shortfall_</span><span>(</span><span>shortfall</span><span>) {}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>    </span><span>double</span><span> </span><span>shortfall</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>shortfall_</span><span>; }</span><span>   // 附带业务数据</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>void</span><span> </span><span>withdraw</span><span>(</span><span>double</span><span><span> </span><span>balance</span><span>, </span></span><span>double</span><span><span> </span><span>amount</span><span>) {</span></span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span> (</span><span>amount</span><span> </span><span>&gt;</span><span> </span><span>balance</span><span>)</span></div></div><div><div><div>16</div></div><div><span>        </span><span>throw</span><span> </span><span>InsufficientFundsError</span><span>(</span><span>amount</span><span> </span><span>-</span><span> </span><span>balance</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>// ...</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>21</div></div><div><span>    </span><span>try</span><span> { </span><span>withdraw</span><span>(</span><span>100</span><span>, </span><span>150</span><span>); }</span></div></div><div><div><div>22</div></div><div><span>    </span><span>catch</span><span> (</span><span>const</span><span> </span><span>InsufficientFundsError</span><span>&amp;</span><span> </span><span>e</span><span>) {</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>what</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span><span>          // 余额不足，还差 50.000000 元</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"缺口: "</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>shortfall</span><span>();</span><span> // 附带数据</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>noexcept 与栈展开<a href="#noexcept-与栈展开"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// noexcept 承诺"此函数不抛异常"——编译器可优化，违诺直接 std::terminate</span></div></div><div><div><div>2</div></div><div><span>void</span><span> </span><span>pure_compute</span><span>(</span><span>int</span><span><span> </span><span>x</span><span>) </span></span><span>noexcept</span><span> {</span><span> /* 不抛任何东西 */</span><span> }</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 异常抛出时的"栈展开"：沿途所有局部对象析构函数被依次调用</span></div></div><div><div><div>5</div></div><div><span>// → RAII 对象在异常路径同样安全释放（这就是 RAII 伟大的原因）</span></div></div><div><div><div>6</div></div><div><span>void</span><span> </span><span>demo</span><span>() {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>FileLogger</span><span> </span><span>log</span><span>(</span><span>"app.log"</span><span>);</span><span>     // 第八篇的 RAII 类</span></div></div><div><div><div>8</div></div><div><span>    </span><span>throw</span><span> std::</span><span>runtime_error</span><span>(</span><span>"boom"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span><span>   // log 的析构依然执行，文件被正确关闭！</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>异常安全军规</strong>：资源交给 RAII 对象管理，异常来了自动清理；不要在析构函数里抛异常。</p></section></section>
<section><h2>二、文件 IO<a href="#二文件-io"><span>#</span></a></h2><section><h3>文本文件：ifstream / ofstream<a href="#文本文件ifstream--ofstream"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;fstream&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>// —— 写文件（ofstream）——</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>std::</span><span>ofstream</span><span> </span><span>out</span><span>(</span><span>"diary.txt"</span><span>);</span><span>           // 默认覆盖模式</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span>out</span><span>) {</span><span>                               // 检查打开是否成功！</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>std::</span><span>cerr</span><span> </span><span>&lt;&lt;</span><span> </span><span>"无法创建文件</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>    </span><span>out</span><span> </span><span>&lt;&lt;</span><span> </span><span>"2026-10-29 学完 C++ 文件IO</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>out</span><span> </span><span>&lt;&lt;</span><span> </span><span>"今天写了 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>3</span><span> </span><span>&lt;&lt;</span><span> </span><span>" 个模块</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>out</span><span>.</span><span>close</span><span>();</span><span>                              // 可显式关，析构也会关</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>// 追加模式</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>std::</span><span>ofstream</span><span> </span><span>append</span><span>(</span><span>"diary.txt"</span><span>, std::ios::</span><span>app</span><span>);</span></div></div><div><div><div>18</div></div><div><span>    </span><span>append</span><span> </span><span>&lt;&lt;</span><span> </span><span>"追加一行</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>// —— 读文件（ifstream）——</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>std::</span><span>ifstream</span><span> </span><span>in</span><span>(</span><span>"diary.txt"</span><span>);</span></div></div><div><div><div>22</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span>in</span><span>) { std::</span><span>cerr</span><span> </span><span>&lt;&lt;</span><span> </span><span>"文件不存在</span><span>\n</span><span>"</span><span>; </span><span>return</span><span> </span><span>1</span><span>; }</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>line</span><span>;</span></div></div><div><div><div>25</div></div><div><span>    </span><span>while</span><span><span> (</span><span>std</span><span>::</span></span><span>getline</span><span>(</span><span>in</span><span>, </span><span>line</span><span>))</span><span>            // 逐行读（自动去 \n）</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"&gt; "</span><span> </span><span>&lt;&lt;</span><span> </span><span>line</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>// 第二种：流提取（按空格分词）</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>std::</span><span>ifstream</span><span> </span><span>in2</span><span>(</span><span>"diary.txt"</span><span>);</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>word</span><span>;</span></div></div><div><div><div>31</div></div><div><span>    </span><span>while</span><span> (</span><span>in2</span><span> </span><span>&gt;&gt;</span><span> </span><span>word</span><span>)</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>word</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>33</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>状态检查与打开模式<a href="#状态检查与打开模式"><span>#</span></a></h3>

<table><thead><tr><th>模式</th><th>含义</th></tr></thead><tbody><tr><td><code>std::ios::in</code></td><td>读</td></tr><tr><td><code>std::ios::out</code></td><td>写（截断）</td></tr><tr><td><code>std::ios::app</code></td><td>追加</td></tr><tr><td><code>std::ios::ate</code></td><td>打开即定位到末尾</td></tr><tr><td><code>std::ios::binary</code></td><td>二进制模式</td></tr></tbody></table><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>std::</span><span>ifstream</span><span> </span><span>f</span><span>(</span><span>"data.txt"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>if</span><span> (</span><span>!</span><span>f</span><span>.</span><span>is_open</span><span>()) {</span><span> /* 打不开 */</span><span> }</span></div></div><div><div><div>3</div></div><div><span>if</span><span> (</span><span>f</span><span>.</span><span>eof</span><span>())  {</span><span> /* 读到文件尾 */</span><span> }</span></div></div><div><div><div>4</div></div><div><span>f</span><span>.</span><span>clear</span><span>();</span><span>                                 // 清除错误状态（重读前）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>stringstream：内存中的流（第五篇分割的完整版）<a href="#stringstream内存中的流第五篇分割的完整版"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;sstream&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// 字符串 → 数值：split 一行 CSV</span></div></div><div><div><div>4</div></div><div><span>std::</span><span>string</span><span> </span><span>line</span><span> </span><span>=</span><span> </span><span>"小明,18,90.5"</span><span>;</span></div></div><div><div><div>5</div></div><div><span>std::</span><span>stringstream</span><span> </span><span>ss</span><span>(</span><span>line</span><span>);</span></div></div><div><div><div>6</div></div><div><span>std::</span><span>string</span><span> </span><span>name</span><span>; </span><span>int</span><span> </span><span>age</span><span>; </span><span>double</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>std</span><span>::</span></span><span>getline</span><span>(</span><span>ss</span><span>, </span><span>name</span><span>, </span><span>','</span><span>);</span></div></div><div><div><div>8</div></div><div><span>ss</span><span> </span><span>&gt;&gt;</span><span> </span><span>age</span><span>; </span><span>ss</span><span>.</span><span>ignore</span><span>(</span><span>1</span><span>, </span><span>','</span><span>);</span><span>     // 跳过逗号</span></div></div><div><div><div>9</div></div><div><span>ss</span><span> </span><span>&gt;&gt;</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 数值 → 字符串（to_string 之外的格式化方式）</span></div></div><div><div><div>12</div></div><div><span>std::</span><span>ostringstream</span><span> </span><span>os</span><span>;</span></div></div><div><div><div>13</div></div><div><span>os</span><span> </span><span>&lt;&lt;</span><span> </span><span>"成绩: "</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>fixed</span><span> </span><span>&lt;&lt;</span><span> std::</span><span>setprecision</span><span>(</span><span>1</span><span>) </span><span>&lt;&lt;</span><span> </span><span>score</span><span>;</span></div></div><div><div><div>14</div></div><div><span>std::</span><span>string</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>os</span><span>.</span><span>str</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、综合实战：通讯录管理系统<a href="#三综合实战通讯录管理系统"><span>#</span></a></h2><p>全系列知识集大成：struct + vector + STL 算法 + 异常 + 文件持久化 + 菜单循环。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ===== contacts.cpp 完整可编译运行 =====</span></div></div><div><div><div>2</div></div><div><span>// g++ contacts.cpp -o contacts -std=c++17</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;iostream&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;fstream&gt;</span></div></div><div><div><div>5</div></div><div><span>#include</span><span> </span><span>&lt;sstream&gt;</span></div></div><div><div><div>6</div></div><div><span>#include</span><span> </span><span>&lt;vector&gt;</span></div></div><div><div><div>7</div></div><div><span>#include</span><span> </span><span>&lt;string&gt;</span></div></div><div><div><div>8</div></div><div><span>#include</span><span> </span><span>&lt;algorithm&gt;</span></div></div><div><div><div>9</div></div><div><span>#include</span><span> </span><span>&lt;iomanip&gt;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>struct</span><span> </span><span>Contact</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>name</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>phone</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>group</span><span>;</span><span>      // 分组：朋友/家人/同学...</span></div></div><div><div><div>15</div></div><div><span>};</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>class</span><span> </span><span>ContactBook</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>std::</span><span>vector</span><span>&lt;</span><span>Contact</span><span>&gt; </span><span>data_</span><span>;</span></div></div><div><div><div>19</div></div><div><span>    </span><span>const</span><span> std::</span><span>string</span><span> </span><span>path_</span><span> </span><span>=</span><span> </span><span>"contacts.txt"</span><span>;</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>public:</span></div></div><div><div><div>22</div></div><div><span>    </span><span>class</span><span> </span><span>ContactError</span><span> : </span><span>public</span><span> std::</span><span>runtime_error</span><span> {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>public:</span><span> </span><span>using</span><span> std::runtime_error::</span><span>runtime_error</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>    </span><span>ContactBook</span><span>() { </span><span>load</span><span>(); }</span></div></div><div><div><div>27</div></div><div><span>    </span><span>~ContactBook</span><span>() { </span><span>save</span><span>(); }</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>    </span><span>void</span><span> </span><span>add</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>, </span></span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>phone</span><span>,</span></span></div></div><div><div><div>30</div></div><div><span>             </span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>group</span><span>) {</span></span></div></div><div><div><div>31</div></div><div><span>        </span><span>if</span><span> (</span><span>name</span><span>.</span><span>empty</span><span>()) </span><span>throw</span><span> </span><span>ContactError</span><span>(</span><span>"姓名不能为空"</span><span>);</span></div></div><div><div><div>32</div></div><div><span>        </span><span>if</span><span> (</span><span>find</span><span>(</span><span>name</span><span>))   </span><span>throw</span><span> </span><span>ContactError</span><span>(</span><span>"联系人已存在: "</span><span> </span><span>+</span><span> </span><span>name</span><span>);</span></div></div><div><div><div>33</div></div><div><span>        </span><span>data_</span><span>.</span><span>push_back</span><span>({</span><span>name</span><span>, </span><span>phone</span><span>, </span><span>group</span><span>});</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>    </span><span>bool</span><span> </span><span>remove</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>) {</span></span></div></div><div><div><div>37</div></div><div><span>        </span><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> std::</span><span>remove_if</span><span>(</span><span>data_</span><span>.</span><span>begin</span><span>(), </span><span>data_</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>38</div></div><div><span><span>            </span></span><span>[</span><span>&amp;</span><span>](</span><span>const</span><span> </span><span>Contact</span><span>&amp;</span><span><span> </span><span>c</span><span>){ </span></span><span>return</span><span> </span><span>c</span><span>.</span><span>name</span><span> </span><span>==</span><span> </span><span>name</span><span>; });</span></div></div><div><div><div>39</div></div><div><span>        </span><span>if</span><span> (</span><span>it</span><span> </span><span>==</span><span> </span><span>data_</span><span>.</span><span>end</span><span>()) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>40</div></div><div><span>        </span><span>data_</span><span>.</span><span>erase</span><span>(</span><span>it</span><span>, </span><span>data_</span><span>.</span><span>end</span><span>());</span><span>            // erase-remove 惯用法</span></div></div><div><div><div>41</div></div><div><span>        </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>    </span><span>const</span><span> </span><span>Contact</span><span>*</span><span> </span><span>find</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>name</span><span>) </span></span><span>const</span><span> {</span></div></div><div><div><div>45</div></div><div><span>        </span><span>auto</span><span> </span><span>it</span><span> </span><span>=</span><span> std::</span><span>find_if</span><span>(</span><span>data_</span><span>.</span><span>begin</span><span>(), </span><span>data_</span><span>.</span><span>end</span><span>(),</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>[</span><span>&amp;</span><span>](</span><span>const</span><span> </span><span>Contact</span><span>&amp;</span><span><span> </span><span>c</span><span>){ </span></span><span>return</span><span> </span><span>c</span><span>.</span><span>name</span><span> </span><span>==</span><span> </span><span>name</span><span>; });</span></div></div><div><div><div>47</div></div><div><span>        </span><span>return</span><span> </span><span>it</span><span> </span><span>==</span><span> </span><span>data_</span><span>.</span><span>end</span><span>() </span><span>?</span><span> </span><span>nullptr</span><span> </span><span>:</span><span> </span><span><span>&amp;</span><span>*</span></span><span>it</span><span>;</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>    </span><span>void</span><span> </span><span>list_by_group</span><span>() </span><span>const</span><span> {</span><span>                 // 分组有序输出</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>std::</span><span>map</span><span>&lt;std::</span><span>string</span><span>, std::</span><span>vector</span><span>&lt;std::</span><span>string</span><span>&gt;&gt; </span><span>groups</span><span>;</span></div></div><div><div><div>52</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>c</span><span> : </span><span>data_</span><span>)</span></div></div><div><div><div>53</div></div><div><span>            </span><span>groups</span><span>[</span><span>c</span><span>.</span><span>group</span><span>].</span><span>push_back</span><span>(</span><span>c</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>" ("</span><span> </span><span>+</span><span> </span><span>c</span><span>.</span><span>phone</span><span> </span><span>+</span><span> </span><span>")"</span><span>);</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> [</span><span>g</span><span>, </span><span>names</span><span>] : </span><span>groups</span><span>) {</span></div></div><div><div><div>56</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"【"</span><span> </span><span>&lt;&lt;</span><span> </span><span>g</span><span> </span><span>&lt;&lt;</span><span> </span><span>"】</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>57</div></div><div><span>            </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>n</span><span> : </span><span>names</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"  "</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>58</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>60</div></div><div>
</div></div><div><div><div>61</div></div><div><span>    </span><span>void</span><span> </span><span>search</span><span>(</span><span>const</span><span> std::</span><span>string</span><span>&amp;</span><span><span> </span><span>keyword</span><span>) </span></span><span>const</span><span> {</span><span>   // 模糊查找</span></div></div><div><div><div>62</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"搜索 </span><span>\"</span><span>"</span><span> </span><span>&lt;&lt;</span><span> </span><span>keyword</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\"</span><span>:</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>63</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>c</span><span> : </span><span>data_</span><span>)</span></div></div><div><div><div>64</div></div><div><span>            </span><span>if</span><span> (</span><span>c</span><span>.</span><span>name</span><span>.</span><span>find</span><span>(</span><span>keyword</span><span>) </span><span>!=</span><span> std::string::</span><span>npos</span><span> </span><span>||</span></div></div><div><div><div>65</div></div><div><span>                </span><span>c</span><span>.</span><span>phone</span><span>.</span><span>find</span><span>(</span><span>keyword</span><span>) </span><span>!=</span><span> std::string::</span><span>npos</span><span>)</span></div></div><div><div><div>66</div></div><div><span><span>                </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"  "</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>phone</span></div></div><div><div><div>67</div></div><div><span>                          </span><span>&lt;&lt;</span><span> </span><span>" ["</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>group</span><span> </span><span>&lt;&lt;</span><span> </span><span>"]</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>68</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span>    </span><span>size_t</span><span> </span><span>size</span><span>() </span><span>const</span><span> { </span><span>return</span><span> </span><span>data_</span><span>.</span><span>size</span><span>(); }</span></div></div><div><div><div>71</div></div><div>
</div></div><div><div><div>72</div></div><div><span>private:</span></div></div><div><div><div>73</div></div><div><span>    </span><span>void</span><span> </span><span>load</span><span>() {</span><span>                                // 每行: name,phone,group</span></div></div><div><div><div>74</div></div><div><span><span>        </span></span><span>std::</span><span>ifstream</span><span> </span><span>in</span><span>(</span><span>path_</span><span>);</span></div></div><div><div><div>75</div></div><div><span>        </span><span>if</span><span> (</span><span>!</span><span>in</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>76</div></div><div><span><span>        </span></span><span>std::</span><span>string</span><span> </span><span>line</span><span>;</span></div></div><div><div><div>77</div></div><div><span>        </span><span>while</span><span><span> (</span><span>std</span><span>::</span></span><span>getline</span><span>(</span><span>in</span><span>, </span><span>line</span><span>)) {</span></div></div><div><div><div>78</div></div><div><span><span>            </span></span><span>std::</span><span>stringstream</span><span> </span><span>ss</span><span>(</span><span>line</span><span>);</span></div></div><div><div><div>79</div></div><div><span><span>            </span></span><span>std::</span><span>string</span><span> </span><span>n</span><span>, </span><span>p</span><span>, </span><span>g</span><span>;</span></div></div><div><div><div>80</div></div><div><span>            </span><span>if</span><span><span> (</span><span>std</span><span>::</span></span><span>getline</span><span>(</span><span>ss</span><span>, </span><span>n</span><span>, </span><span>','</span><span>) </span><span>&amp;&amp;</span></div></div><div><div><div>81</div></div><div><span><span>                </span></span><span>std::</span><span>getline</span><span>(</span><span>ss</span><span>, </span><span>p</span><span>, </span><span>','</span><span>) </span><span>&amp;&amp;</span></div></div><div><div><div>82</div></div><div><span><span>                </span></span><span>std::</span><span>getline</span><span>(</span><span>ss</span><span>, </span><span>g</span><span>))</span></div></div><div><div><div>83</div></div><div><span>                </span><span>data_</span><span>.</span><span>push_back</span><span>({</span><span>n</span><span>, </span><span>p</span><span>, </span><span>g</span><span>});</span></div></div><div><div><div>84</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>85</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>86</div></div><div><span>    </span><span>void</span><span> </span><span>save</span><span>() </span><span>const</span><span> {</span></div></div><div><div><div>87</div></div><div><span><span>        </span></span><span>std::</span><span>ofstream</span><span> </span><span>out</span><span>(</span><span>path_</span><span>);</span><span>                // 覆盖重写</span></div></div><div><div><div>88</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>auto&amp;</span><span> </span><span>c</span><span> : </span><span>data_</span><span>)</span></div></div><div><div><div>89</div></div><div><span>            </span><span>out</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>phone</span><span> </span><span>&lt;&lt;</span><span> </span><span>","</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>.</span><span>group</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>90</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>91</div></div><div><span>};</span></div></div><div><div><div>92</div></div><div>
</div></div><div><div><div>93</div></div><div><span>int</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>94</div></div><div><span>    </span><span>ContactBook</span><span> </span><span>book</span><span>;</span></div></div><div><div><div>95</div></div><div>
</div></div><div><div><div>96</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"=== 通讯录 ===</span><span>\n</span><span>"</span></div></div><div><div><div>97</div></div><div><span>              </span><span>&lt;&lt;</span><span> </span><span>"add 名字 电话 分组 | del 名字 | find 名字 | "</span></div></div><div><div><div>98</div></div><div><span>                 </span><span>"search 关键词 | list | quit</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>99</div></div><div>
</div></div><div><div><div>100</div></div><div><span><span>    </span></span><span>std::</span><span>string</span><span> </span><span>cmd</span><span>;</span></div></div><div><div><div>101</div></div><div><span>    </span><span>while</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>102</div></div><div><span><span>        </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>&gt; "</span><span>;</span></div></div><div><div><div>103</div></div><div><span>        </span><span>if</span><span> (</span><span>!</span><span>(std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>cmd</span><span>)) </span><span>break</span><span>;</span></div></div><div><div><div>104</div></div><div>
</div></div><div><div><div>105</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>106</div></div><div><span>            </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"quit"</span><span>) </span><span>break</span><span>;</span></div></div><div><div><div>107</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"add"</span><span>) {</span></div></div><div><div><div>108</div></div><div><span><span>                </span></span><span>std::</span><span>string</span><span> </span><span>n</span><span>, </span><span>p</span><span>, </span><span>g</span><span>;</span></div></div><div><div><div>109</div></div><div><span><span>                </span></span><span>std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span> </span><span>&gt;&gt;</span><span> </span><span>p</span><span> </span><span>&gt;&gt;</span><span> </span><span>g</span><span>;</span></div></div><div><div><div>110</div></div><div><span>                </span><span>book</span><span>.</span><span>add</span><span>(</span><span>n</span><span>, </span><span>p</span><span>, </span><span>g</span><span>);</span></div></div><div><div><div>111</div></div><div><span><span>                </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"✅ 已添加 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>n</span><span> </span><span>&lt;&lt;</span><span> </span><span>"（共 "</span><span> </span><span>&lt;&lt;</span><span> </span><span>book</span><span>.</span><span>size</span><span>() </span><span>&lt;&lt;</span><span> </span><span>" 人）</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>112</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>113</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"del"</span><span>) {</span></div></div><div><div><div>114</div></div><div><span><span>                </span></span><span>std::</span><span>string</span><span> </span><span>n</span><span>; std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>115</div></div><div><span><span>                </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> (</span><span>book</span><span>.</span><span>remove</span><span>(</span><span>n</span><span>) </span><span>?</span><span> </span><span>"🗑 已删除"</span><span> </span><span>:</span><span> </span><span>"没找到"</span><span>) </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>116</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>117</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"find"</span><span>) {</span></div></div><div><div><div>118</div></div><div><span><span>                </span></span><span>std::</span><span>string</span><span> </span><span>n</span><span>; std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>n</span><span>;</span></div></div><div><div><div>119</div></div><div><span>                </span><span>const</span><span> </span><span>Contact</span><span>*</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>book</span><span>.</span><span>find</span><span>(</span><span>n</span><span>);</span></div></div><div><div><div>120</div></div><div><span>                </span><span>if</span><span> (</span><span>c</span><span>) std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>-&gt;</span><span>name</span><span> </span><span>&lt;&lt;</span><span> </span><span>" "</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>-&gt;</span><span>phone</span></div></div><div><div><div>121</div></div><div><span>                                 </span><span>&lt;&lt;</span><span> </span><span>" ["</span><span> </span><span>&lt;&lt;</span><span> </span><span>c</span><span>-&gt;</span><span>group</span><span> </span><span>&lt;&lt;</span><span> </span><span>"]</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>122</div></div><div><span>                </span><span>else</span><span>   std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"没找到</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>123</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>124</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"search"</span><span>) { std::</span><span>string</span><span> </span><span>k</span><span>; std::</span><span>cin</span><span> </span><span>&gt;&gt;</span><span> </span><span>k</span><span>; </span><span>book</span><span>.</span><span>search</span><span>(</span><span>k</span><span>); }</span></div></div><div><div><div>125</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span> (</span><span>cmd</span><span> </span><span>==</span><span> </span><span>"list"</span><span>)   { </span><span>book</span><span>.</span><span>list_by_group</span><span>(); }</span></div></div><div><div><div>126</div></div><div><span>            </span><span>else</span><span> std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"未知命令</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>127</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>128</div></div><div><span>        </span><span>catch</span><span> (</span><span>const</span><span> ContactBook::</span><span>ContactError</span><span>&amp;</span><span> </span><span>e</span><span>) {</span></div></div><div><div><div>129</div></div><div><span><span>            </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"❌ "</span><span> </span><span>&lt;&lt;</span><span> </span><span>e</span><span>.</span><span>what</span><span>() </span><span>&lt;&lt;</span><span> </span><span>"</span><span>\n</span><span>"</span><span>;</span></div></div><div><div><div>130</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>131</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>132</div></div><div><span><span>    </span></span><span>std::</span><span>cout</span><span> </span><span>&lt;&lt;</span><span> </span><span>"数据已保存，再见！</span><span>\n</span><span>"</span><span>;</span><span>      // 析构也会 save</span></div></div><div><div><div>133</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>用到的知识点清单</strong>：struct、class 封装、vector + 算法（find_if/remove_if）、map 分组、异常（自定义 + try/catch）、文件读写（ifstream/ofstream）、stringstream 解析、RAII（析构自动保存）。</p><p><strong>运行演示</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&gt; add 小明 138xxxx 同学</span></div></div><div><div><div>2</div></div><div><span>✅ 已添加 小明（共 1 人）</span></div></div><div><div><div>3</div></div><div><span>&gt; add 小红 139xxxx 家人</span></div></div><div><div><div>4</div></div><div><span>✅ 已添加 小红（共 2 人）</span></div></div><div><div><div>5</div></div><div><span>&gt; add 小明 137xxxx 朋友</span></div></div><div><div><div>6</div></div><div><span>❌ 联系人已存在: 小明</span></div></div><div><div><div>7</div></div><div><span>&gt; list</span></div></div><div><div><div>8</div></div><div><span>【同学】</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>小明 (138xxxx)</span></div></div><div><div><div>10</div></div><div><span>【家人】</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>小红 (139xxxx)</span></div></div><div><div><div>12</div></div><div><span>&gt; quit</span></div></div><div><div><div>13</div></div><div><span>数据已保存，再见！</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>四、系列总结<a href="#四系列总结"><span>#</span></a></h2>

<table><thead><tr><th>篇</th><th>主题</th><th>关键收获</th></tr></thead><tbody><tr><td>1</td><td>环境与第一个程序</td><td>g++ 编译流程、main、cout/cin</td></tr><tr><td>2</td><td>语法与运算符</td><td>七类运算、类型转换、cin 校验</td></tr><tr><td>3</td><td>流程控制</td><td>switch/循环/范围 for/经典练习</td></tr><tr><td>4</td><td>函数</td><td>声明定义分离、三种传参、重载、默认参数</td></tr><tr><td>5</td><td>数组与字符串</td><td>数组局限、vector/string 全家桶</td></tr><tr><td>6</td><td>指针与引用</td><td>内存模型、new/delete、智能指针</td></tr><tr><td>7</td><td>结构体与枚举</td><td>自定义类型、enum class</td></tr><tr><td>8</td><td>面向对象（上）</td><td>封装、构造析构、三法则、RAII</td></tr><tr><td>9</td><td>面向对象（下）</td><td>继承、虚函数多态、抽象类、虚析构</td></tr><tr><td>10</td><td>运算符重载</td><td>算术/流/下标重载、友元</td></tr><tr><td>11</td><td>STL</td><td>容器选型、迭代器、算法库</td></tr><tr><td>12</td><td>异常/IO/实战（本篇）</td><td>try/catch、文件流、综合项目</td></tr></tbody></table><p><strong>下一步</strong>：数据结构与算法（用 C++ 实现一遍链表/栈/队列/树）、或挑战小型项目（JSON 解析器、简易 HTTP 服务器、贪吃蛇）。做出作品欢迎投稿本站！</p></section>
<section><h2>小练习（毕业设计）<a href="#小练习毕业设计"><span>#</span></a></h2><ol>
<li>通讯录加”修改”命令（update 名字 新电话）与”导入导出 CSV”</li>
<li>把通讯录数据改成 JSON 风格存储（自己设计转义规则）</li>
<li>用 class 重写第三篇猜数字为 <code>GuessGame</code> 类，含 <code>play()</code> 与统计功能</li>
</ol><hr /><p><em>本系列为 Cyber先锋社原创教程，共 12 篇完结。欢迎在留言板晒出你的毕业设计！</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-01/</id>
      <title type="text">Java 入门教程（一）：JDK、IDEA 与第一个程序</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-01/"/>
      <summary type="text">进入 Java 的世界：理解&quot;一次编写，到处运行&quot;的原理、安装 JDK 与 IDEA、解剖第一个程序的结构、掌握变量与数据类型。企业级开发语言的起点。</summary>
      <content type="html"><![CDATA[<section><h2>Java 的定位<a href="#java-的定位"><span>#</span></a></h2><p>“一次编写，到处运行”（Write Once, Run Anywhere）是 Java 的招牌。它能做到这一点，靠的是 <strong>JVM（Java 虚拟机）</strong>：Java 源代码先编译成”字节码”（<code>.class</code> 文件），再由各平台的 JVM 执行——同一个字节码能在 Windows、macOS、Linux 上运行。</p><p>Java 是企业级开发的主力语言：银行系统、安卓 App、大型电商后端、大数据生态（Hadoop/Spark 均为 Java 系）都有它的身影。岗位多、生态成熟，是就业市场的常青树。</p></section>
<section><h2>JDK / JRE / JVM 的关系<a href="#jdk--jre--jvm-的关系"><span>#</span></a></h2><p>初学必懂的三层概念：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>JDK（开发工具包）</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>├── JRE（运行环境）</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>│    ├── JVM（虚拟机：真正执行字节码）</span></div></div><div><div><div>4</div></div><div><span><span> </span></span><span>│    └── 核心类库</span></div></div><div><div><div>5</div></div><div><span><span> </span></span><span>├── javac（编译器）</span></div></div><div><div><div>6</div></div><div><span><span> </span></span><span>└── 其他开发工具</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>只想<strong>运行</strong> Java 程序 → 装 JRE 就够</li>
<li>想<strong>开发</strong> Java 程序 → 装 JDK（包含 JRE）</li>
</ul></section>
<section><h2>安装 JDK 与开发环境<a href="#安装-jdk-与开发环境"><span>#</span></a></h2><section><h3>安装 JDK（推荐 LTS 版本 17 或 21）<a href="#安装-jdk推荐-lts-版本-17-或-21"><span>#</span></a></h3><p><strong>Windows/macOS</strong>：从 <a href="https://adoptium.net/" target="_blank">Adoptium</a>（Eclipse Temurin 发行版）下载安装包，一路下一步。</p><p><strong>Linux（Ubuntu/Debian）</strong>：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span><span> &amp;&amp; </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>openjdk-21-jdk</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>验证安装<a href="#验证安装"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>java</span><span> </span><span>-version</span><span>     </span><span># 运行环境版本</span></div></div><div><div><div>2</div></div><div><span>javac</span><span> </span><span>-version</span><span>    </span><span># 编译器版本</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>两个命令都有输出即安装成功。</p></section><section><h3>安装 IDEA<a href="#安装-idea"><span>#</span></a></h3><p>Java 开发的事实标准 IDE 是 <strong>IntelliJ IDEA</strong>（JetBrains 出品）：</p><ol>
<li>到 <a href="https://www.jetbrains.com/idea/" target="_blank">jetbrains.com/idea</a> 下载</li>
<li>学生可申请免费的教育许可（Community 社区版本身也免费且够用）</li>
<li>首次使用学生邮箱激活 Ultimate 教育版更香</li>
</ol><div><div><div></div><div>Tip</div></div><div><p>新手完全可以用 Community 社区版起步，功能足够写完整个入门系列。</p></div></div></section></section>
<section><h2>第一个程序<a href="#第一个程序"><span>#</span></a></h2><p>新建 <code>Hello.java</code>（<strong>文件名必须与类名一致</strong>，这是 Java 的硬规矩）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Hello</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Hello, Cyber先锋社!"</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译运行：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>javac</span><span> </span><span>Hello.java</span><span>    </span><span># 生成 Hello.class 字节码</span></div></div><div><div><div>2</div></div><div><span>java</span><span> </span><span>Hello</span><span>          </span><span># JVM 执行（注意不带 .class 后缀）</span></div></div><div><div><div>3</div></div><div><span>Hello,</span><span> </span><span>Cyber先锋社!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在 IDEA 里只需右键 → Run，IDE 会自动完成编译执行。</p><p><strong>解剖这个程序</strong>：</p>

<table><thead><tr><th>部分</th><th>含义</th></tr></thead><tbody><tr><td><code>public class Hello</code></td><td>定义一个公开类，类名与文件名一致</td></tr><tr><td><code>public static void main(String[] args)</code></td><td>主方法：程序入口，格式固定照抄</td></tr><tr><td><code>System.out.println(...)</code></td><td>向控制台输出一行内容</td></tr><tr><td><code>;</code></td><td>每条语句以分号结尾</td></tr></tbody></table><div><div><div></div><div>Warning</div></div><div><p>Java 对大小写极其敏感：<code>System</code> 写成 <code>system</code> 直接报错。<code>main</code> 方法的签名必须一字不差。</p></div></div></section>
<section><h2>变量与数据类型<a href="#变量与数据类型"><span>#</span></a></h2><p>Java 同样是静态类型语言，且区分<strong>基本类型</strong>与<strong>引用类型</strong>：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Types</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>// 基本类型（8 种，入门先掌握这几种）</span></div></div><div><div><div>4</div></div><div><span>        </span><span>int</span><span><span> </span><span>age</span><span> </span></span><span><span>=</span><span> </span></span><span>18</span><span>;               </span><span>// 整数</span></div></div><div><div><div>5</div></div><div><span>        </span><span>long</span><span><span> </span><span>views</span><span> </span></span><span><span>=</span><span> </span></span><span>10000000000L</span><span>;  </span><span>// 长整数（注意 L 后缀）</span></div></div><div><div><div>6</div></div><div><span>        </span><span>double</span><span><span> </span><span>price</span><span> </span></span><span><span>=</span><span> </span></span><span>9.9</span><span>;         </span><span>// 双精度浮点</span></div></div><div><div><div>7</div></div><div><span>        </span><span>char</span><span><span> </span><span>grade</span><span> </span></span><span><span>=</span><span> </span></span><span>'A'</span><span>;           </span><span>// 单字符，单引号</span></div></div><div><div><div>8</div></div><div><span>        </span><span>boolean</span><span><span> </span><span>passed</span><span> </span></span><span><span>=</span><span> </span></span><span>true</span><span>;      </span><span>// 布尔值</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>// 引用类型：字符串（双引号）</span></div></div><div><div><div>11</div></div><div><span>        </span><span>String</span><span><span> </span><span>name</span><span> </span></span><span><span>=</span><span> </span></span><span>"小明"</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>// var 关键字（Java 10+）：编译器自动推断类型</span></div></div><div><div><div>14</div></div><div><span>        </span><span>var</span><span><span> </span><span>message</span><span> </span></span><span><span>=</span><span> </span></span><span>"类型推断"</span><span>;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>" "</span><span><span> </span><span>+</span><span> age </span><span>+</span><span> </span></span><span>" 岁"</span><span>);</span></div></div><div><div><div>17</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"价格: %.2f 元%n"</span><span>, price);   </span><span>// 格式化输出</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><section><h3>基本类型速览<a href="#基本类型速览"><span>#</span></a></h3>

<table><thead><tr><th>类型</th><th>字节</th><th>说明</th></tr></thead><tbody><tr><td><code>byte</code></td><td>1</td><td>小整数 ±128</td></tr><tr><td><code>int</code></td><td>4</td><td>常用整数 ±21 亿</td></tr><tr><td><code>long</code></td><td>8</td><td>大整数，字面量加 <code>L</code></td></tr><tr><td><code>double</code></td><td>8</td><td>常用小数</td></tr><tr><td><code>char</code></td><td>2</td><td>单字符（Unicode）</td></tr><tr><td><code>boolean</code></td><td>—</td><td>true / false</td></tr></tbody></table></section><section><h3>类型转换<a href="#类型转换"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>double</span><span> b </span><span><span>=</span><span> a</span><span>;</span><span>          </span></span><span>// 自动转换（小 → 大，安全）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>double</span><span> pi </span><span><span>=</span><span> </span></span><span>3.99</span><span>;</span></div></div><div><div><div>5</div></div><div><span>int</span><span> c </span><span><span>=</span><span> (</span></span><span>int</span><span><span>) pi</span><span>;</span><span>      </span></span><span>// 强制转换（大 → 小，截断小数），c = 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>输入：Scanner<a href="#输入scanner"><span>#</span></a></h2><p>Java 读键盘输入用 <code>Scanner</code> 类：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Scanner</span><span><span>;</span><span>   </span></span><span>// 导包</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>InputDemo</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>System</span><span>.</span><span>in</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"输入你的名字: "</span><span>);</span></div></div><div><div><div>8</div></div><div><span>        </span><span>String</span><span><span> </span><span>name</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>next</span><span>();          </span><span>// 读一个词</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"输入你的年龄: "</span><span>);</span></div></div><div><div><div>11</div></div><div><span>        </span><span>int</span><span><span> </span><span>age</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextInt</span><span>();           </span><span>// 读一个整数</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>" 明年 "</span><span><span> </span><span>+</span><span> (age </span><span>+</span><span> </span></span><span>1</span><span><span>) </span><span>+</span><span> </span></span><span>" 岁"</span><span>);</span></div></div><div><div><div>14</div></div><div><span>        </span><span>sc</span><span>.</span><span>close</span><span>();</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>三个语言横向对比（入门篇）<a href="#三个语言横向对比入门篇"><span>#</span></a></h2><p>学到这里可以横向看看三姐妹的差异：</p>

<table><thead><tr><th>特性</th><th>Python</th><th>C++</th><th>Java</th></tr></thead><tbody><tr><td>执行方式</td><td>解释执行</td><td>编译为机器码</td><td>编译为字节码 + JVM</td></tr><tr><td>类型系统</td><td>动态</td><td>静态</td><td>静态</td></tr><tr><td>语法复杂度</td><td>最低</td><td>最高</td><td>中等</td></tr><tr><td>典型用途</td><td>AI、脚本、数据</td><td>游戏、系统、嵌入式</td><td>企业后端、安卓</td></tr><tr><td>入门友好度</td><td>⭐⭐⭐⭐⭐</td><td>⭐⭐⭐</td><td>⭐⭐⭐⭐</td></tr></tbody></table></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写程序输出你的个人信息卡（姓名/年龄/专业/一句座右铭），每行一项</li>
<li>用 <code>Scanner</code> 读入长和宽，输出矩形面积与周长</li>
<li>已知某商品原价与折扣（如 88 折），计算折后价并保留两位小数（<code>printf</code> 的 <code>%.2f</code>）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>JDK = 开发工具集；JVM 负责执行字节码，实现跨平台</li>
<li><code>javac</code> 编译 → <code>java</code> 运行；IDEA 可以一键搞定</li>
<li>文件名必须与 <code>public</code> 类名一致；<code>main</code> 方法是固定入口</li>
<li>8 种基本类型 + <code>String</code> 引用类型；<code>var</code> 可自动推断</li>
<li><code>Scanner</code> 处理键盘输入，用完记得 <code>close()</code></li>
</ul><p><strong>下一篇</strong>：流程控制与方法——把逻辑组织成可复用的积木。</p><hr /><p><em>本系列为 Cyber先锋社原创教程，参考业界通用知识体系编写。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-02/</id>
      <title type="text">Java 入门教程（二）：语法基础与运算符</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-02/"/>
      <summary type="text">详解 Java 基本语法：注释、变量与常量、八种基本类型与类型转换规则、七类运算符、Scanner 输入进阶与 printf 格式化，配典型陷阱与对照示例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>上一篇跑通了第一个程序，本篇夯实 Java 语法地基：类型系统、运算符、输入输出。Java 是强类型语言的典范——类型规则比 Python 严、比 C++ 更”啰嗦”但更统一。</p></section>
<section><h2>一、注释与命名规范<a href="#一注释与命名规范"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 单行注释</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>/* 多行注释 */</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>/**</span></div></div><div><div><div>6</div></div><div><span><span> </span></span><span>* 文档注释（javadoc）：IDE 悬停提示、官方文档都靠它</span></div></div><div><div><div>7</div></div><div><span><span> </span></span><span>* </span><span>@param</span><span> </span><span>a</span><span> 加数</span></div></div><div><div><div>8</div></div><div><span><span> </span></span><span>* </span><span>@return</span><span> 两数之和</span></div></div><div><div><div>9</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>10</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span> </span><span>add</span><span>(</span><span>int</span><span><span> a</span><span>,</span><span> </span></span><span>int</span><span> b) { </span><span>return</span><span><span> a </span><span>+</span><span> b</span><span>;</span><span> }</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Java 命名惯例</strong>（社区铁律）：</p>

<table><thead><tr><th>元素</th><th>规范</th><th>示例</th></tr></thead><tbody><tr><td>类名</td><td>大驼峰</td><td><code>StudentManager</code></td></tr><tr><td>方法/变量</td><td>小驼峰</td><td><code>calcAverage</code>、<code>maxScore</code></td></tr><tr><td>常量</td><td>全大写下划线</td><td><code>MAX_SIZE</code></td></tr><tr><td>包名</td><td>全小写</td><td><code>com.club.utils</code></td></tr></tbody></table></section>
<section><h2>二、变量与基本类型<a href="#二变量与基本类型"><span>#</span></a></h2><section><h3>八大基本类型<a href="#八大基本类型"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Types</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>// 整数家族</span></div></div><div><div><div>4</div></div><div><span>        </span><span>byte</span><span><span> </span><span>b</span><span> </span></span><span><span>=</span><span> </span></span><span>127</span><span>;                  </span><span>// 1字节 ±128</span></div></div><div><div><div>5</div></div><div><span>        </span><span>short</span><span><span> </span><span>s</span><span> </span></span><span><span>=</span><span> </span></span><span>32000</span><span>;               </span><span>// 2字节</span></div></div><div><div><div>6</div></div><div><span>        </span><span>int</span><span><span> </span><span>i</span><span> </span></span><span><span>=</span><span> </span></span><span>2147483647</span><span>;            </span><span>// 4字节（默认整数字面量类型）</span></div></div><div><div><div>7</div></div><div><span>        </span><span>long</span><span><span> </span><span>big</span><span> </span></span><span><span>=</span><span> </span></span><span>10000000000L</span><span>;       </span><span>// 8字节（注意 L 后缀！）</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>        </span><span>// 浮点家族</span></div></div><div><div><div>10</div></div><div><span>        </span><span>float</span><span><span> </span><span>f</span><span> </span></span><span><span>=</span><span> </span></span><span>3.14f</span><span>;               </span><span>// 4字节（注意 f 后缀！）</span></div></div><div><div><div>11</div></div><div><span>        </span><span>double</span><span><span> </span><span>d</span><span> </span></span><span><span>=</span><span> </span></span><span>3.14159265358979</span><span>;   </span><span>// 8字节（默认小数字面量类型）</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>// 其他</span></div></div><div><div><div>14</div></div><div><span>        </span><span>char</span><span><span> </span><span>c</span><span> </span></span><span><span>=</span><span> </span></span><span>'A'</span><span>;                  </span><span>// 2字节 Unicode 单字符</span></div></div><div><div><div>15</div></div><div><span>        </span><span>char</span><span><span> </span><span>chinese</span><span> </span></span><span><span>=</span><span> </span></span><span>'先'</span><span>;           </span><span>// ✓ 中文也是 char</span></div></div><div><div><div>16</div></div><div><span>        </span><span>boolean</span><span><span> </span><span>ok</span><span> </span></span><span><span>=</span><span> </span></span><span>true</span><span>;             </span><span>// true/false（不是 1/0！）</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>        </span><span>// 类型大小永不变（跨平台一致，这是 Java 的卖点）</span></div></div><div><div><div>19</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Integer</span><span>.</span><span>SIZE</span><span><span> </span><span>/</span><span> </span></span><span>8</span><span>);    </span><span>// 4 字节</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div></div><div>Warning</div></div><div><p>与 C++ 不同：Java 的 <code>boolean</code> 不是整数，<code>if (1)</code> 直接编译错误；<code>char</code> 是 16 位 Unicode。</p></div></div></section><section><h3>var 局部变量推断（Java 10+）<a href="#var-局部变量推断java-10"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span> name </span><span><span>=</span><span> </span></span><span>"小明"</span><span><span>;</span><span>            </span></span><span>// String</span></div></div><div><div><div>2</div></div><div><span>var</span><span> age </span><span><span>=</span><span> </span></span><span>18</span><span><span>;</span><span>                  </span></span><span>// int</span></div></div><div><div><div>3</div></div><div><span>var</span><span> scores </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[]{</span><span>90</span><span><span>,</span><span> </span></span><span>85</span><span><span>}</span><span>;</span><span>   </span></span><span>// int[]</span></div></div><div><div><div>4</div></div><div><span>// var x;                      // ❌ 必须初始化</span></div></div><div><div><div>5</div></div><div><span>// var 只能用于局部变量，不能用于字段和参数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>常量<a href="#常量"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Config</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>final</span><span> </span><span>double</span><span> TAX_RATE </span><span><span>=</span><span> </span></span><span>0.13</span><span><span>;</span><span>    </span></span><span>// 类级常量：final + static</span></div></div><div><div><div>3</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>final</span><span> </span><span>int</span><span> MAX_RETRY </span><span><span>=</span><span> </span></span><span>3</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>final</span><span> </span><span>int</span><span> LOCAL_MAX </span><span><span>=</span><span> </span></span><span>100</span><span><span>;</span><span>     </span></span><span>// 局部常量：赋值后不可改</span></div></div><div><div><div>7</div></div><div><span>// LOCAL_MAX = 200;            // ❌ 编译错误</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>默认值（成员变量才有！）<a href="#默认值成员变量才有"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Demo</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> a</span><span><span>;</span><span>           </span></span><span>// 0</span></div></div><div><div><div>3</div></div><div><span>    </span><span>static</span><span> </span><span>double</span><span> d</span><span><span>;</span><span>        </span></span><span>// 0.0</span></div></div><div><div><div>4</div></div><div><span>    </span><span>static</span><span> </span><span>boolean</span><span> flag</span><span><span>;</span><span>    </span></span><span>// false</span></div></div><div><div><div>5</div></div><div><span>    </span><span>static</span><span> </span><span>String</span><span> s</span><span><span>;</span><span>        </span></span><span>// null（引用类型默认 null）</span></div></div><div><div><div>6</div></div><div><span>    </span><span>// ⚠ 局部变量没有默认值，未初始化直接用 → 编译错误</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、类型转换<a href="#三类型转换"><span>#</span></a></h2><section><h3>自动转换（小 → 大，安全）<a href="#自动转换小--大安全"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>100</span><span>;</span></div></div><div><div><div>2</div></div><div><span>long</span><span> l </span><span><span>=</span><span> i</span><span>;</span><span>         </span></span><span>// ✓ int → long</span></div></div><div><div><div>3</div></div><div><span>double</span><span> d </span><span><span>=</span><span> l</span><span>;</span><span>       </span></span><span>// ✓ long → double</span></div></div><div><div><div>4</div></div><div><span>double</span><span> d2 </span><span><span>=</span><span> </span></span><span>10</span><span><span>;</span><span>     </span></span><span>// ✓ int 字面量直接给 double</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>char</span><span> c </span><span><span>=</span><span> </span></span><span>'A'</span><span>;</span></div></div><div><div><div>7</div></div><div><span>int</span><span> code </span><span><span>=</span><span> c</span><span>;</span><span>       </span></span><span>// ✓ 65</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>强制转换（大 → 小，可能丢失）<a href="#强制转换大--小可能丢失"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>double</span><span> pi </span><span><span>=</span><span> </span></span><span>3.99</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> truncated </span><span><span>=</span><span> (</span></span><span>int</span><span><span>) pi</span><span>;</span><span>       </span></span><span>// 3（直接截断，不是四舍五入！）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>long</span><span> big </span><span><span>=</span><span> </span></span><span>10000000000L</span><span>;</span></div></div><div><div><div>5</div></div><div><span>int</span><span> overflow </span><span><span>=</span><span> (</span></span><span>int</span><span><span>) big</span><span>;</span><span>       </span></span><span>// 1410065408（高位截断，结果诡异）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 经典陷阱：两个 int 相除</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>7</span><span><span> </span><span>/</span><span> </span></span><span>2</span><span><span>);</span><span>          </span></span><span>// 3（int 除法！）</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>7</span><span><span> </span><span>/</span><span> </span></span><span>2.0</span><span><span>);</span><span>        </span></span><span>// 3.5（一侧 double 则 double）</span></div></div><div><div><div>10</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>((</span><span>double</span><span>) </span><span>7</span><span><span> </span><span>/</span><span> </span></span><span>2</span><span><span>);</span><span> </span></span><span>// 3.5（先转再除）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>数值溢出行为<a href="#数值溢出行为"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> max </span><span><span>=</span><span> </span></span><span>Integer</span><span>.</span><span>MAX_VALUE</span><span>;</span></div></div><div><div><div>2</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(max </span><span>+</span><span> </span></span><span>1</span><span><span>);</span><span>    </span></span><span>// -2147483648（静默回绕！C++ 是未定义，Java 规定为回绕）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>long</span><span> safe </span><span><span>=</span><span> (</span></span><span>long</span><span><span>) max </span><span>+</span><span> </span></span><span>1</span><span><span>;</span><span>     </span></span><span>// ✓ 先升格再运算</span></div></div><div><div><div>5</div></div><div><span>// 大数运算用 long，再大用 java.math.BigInteger</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、运算符全解<a href="#四运算符全解"><span>#</span></a></h2><section><h3>算术<a href="#算术"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>10</span><span><span>,</span><span> b </span><span>=</span><span> </span></span><span>3</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>+</span><span> b);</span><span>      </span></span><span>// 13</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>-</span><span> b);</span><span>      </span></span><span>// 7</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>*</span><span> b);</span><span>      </span></span><span>// 30</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>/</span><span> b);</span><span>      </span></span><span>// 3   整除截断</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>%</span><span> b);</span><span>      </span></span><span>// 1   取模（Java 的 % 可用于负数与浮点）</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(</span><span>-</span></span><span>7</span><span><span> </span><span>%</span><span> </span></span><span>3</span><span><span>);</span><span>     </span></span><span>// -1（余数符号跟被除数）</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>7.5</span><span><span> </span><span>%</span><span> </span></span><span>2</span><span><span>);</span><span>    </span></span><span>// 1.5（浮点取模合法！C++ 不行）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// ++ 与 --</span></div></div><div><div><div>12</div></div><div><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>5</span><span>;</span></div></div><div><div><div>13</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(i++);</span><span>        </span></span><span>// 5 先用后加</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(++i);</span><span>        </span></span><span>// 7 先加后用</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>关系与逻辑<a href="#关系与逻辑"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>5</span><span><span>,</span><span> b </span><span>=</span><span> </span></span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>&gt;</span><span> b);</span><span>      </span></span><span>// false</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 逻辑运算符：&amp; &amp;&amp; | || !</span></div></div><div><div><div>6</div></div><div><span>boolean</span><span> r1 </span><span><span>=</span><span> (a </span><span>&gt;</span><span> </span></span><span>0</span><span><span>) </span><span>&amp;&amp;</span><span> (b </span><span>&gt;</span><span> </span></span><span>0</span><span><span>)</span><span>;</span><span>    </span></span><span>// 短路与（推荐日常用）</span></div></div><div><div><div>7</div></div><div><span>boolean</span><span> r2 </span><span><span>=</span><span> (a </span><span>&gt;</span><span> </span></span><span>0</span><span><span>) </span><span>&amp;</span><span>  (b </span><span>&gt;</span><span> </span></span><span>0</span><span><span>)</span><span>;</span><span>    </span></span><span>// 非短路与（两边都算，位运算语义）</span></div></div><div><div><div>8</div></div><div><span>boolean</span><span> r3 </span><span><span>=</span><span> (a </span><span>&gt;</span><span> </span></span><span>0</span><span><span>) </span><span>||</span><span> (b </span><span>&lt;</span><span> </span></span><span>0</span><span><span>)</span><span>;</span><span>    </span></span><span>// 短路或</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// ⚠ 经典面试点：短路与否影响副作用</span></div></div><div><div><div>11</div></div><div><span>int</span><span> x </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>12</div></div><div><span>boolean</span><span> r </span><span><span>=</span><span> (x </span><span>!=</span><span> </span></span><span>0</span><span><span>) </span><span>&amp;&amp;</span><span> (</span><span>++</span><span>x </span><span>&gt;</span><span> </span></span><span>0</span><span><span>)</span><span>;</span><span>  </span></span><span>// 左边 false，右边不执行</span></div></div><div><div><div>13</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(x);</span><span>              </span></span><span>// 0</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>// Java 特有：异或 ^</span></div></div><div><div><div>16</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>true</span><span><span> </span><span>^</span><span> </span></span><span>false</span><span><span>);</span><span>   </span></span><span>// true</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>位运算（与 C++ 一致）<a href="#位运算与-c-一致"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>0b1010</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>&amp;</span><span> </span></span><span>0b0110</span><span><span>);</span><span>    </span></span><span>// 2</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>|</span><span> </span></span><span>0b0101</span><span><span>);</span><span>    </span></span><span>// 15</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>^</span><span> </span></span><span>0b1111</span><span><span>);</span><span>    </span></span><span>// 5</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(</span><span>~</span><span>a);</span><span>            </span></span><span>// -11</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>&lt;&lt;</span><span> </span></span><span>2</span><span><span>);</span><span>        </span></span><span>// 40</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>&gt;&gt;</span><span> </span></span><span>1</span><span><span>);</span><span>        </span></span><span>// 5  算术右移（补符号位）</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(</span><span>-</span></span><span>8</span><span><span> </span><span>&gt;&gt;&gt;</span><span> </span></span><span>1</span><span><span>);</span><span>      </span></span><span>// 2147483644 逻辑右移（Java 特有 &gt;&gt;&gt;，补 0）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>三元与 instanceof<a href="#三元与-instanceof"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> age </span><span><span>=</span><span> </span></span><span>20</span><span>;</span></div></div><div><div><div>2</div></div><div><span>String</span><span> status </span><span><span>=</span><span> age </span><span>&gt;=</span><span> </span></span><span>18</span><span> </span><span>?</span><span> </span><span>"成年"</span><span> </span><span>:</span><span> </span><span>"未成年"</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// instanceof：判断引用类型（面向对象篇重用）</span></div></div><div><div><div>5</div></div><div><span>Object</span><span> obj </span><span><span>=</span><span> </span></span><span>"hello"</span><span>;</span></div></div><div><div><div>6</div></div><div><span>if</span><span> (obj </span><span>instanceof</span><span> String) {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"长度: "</span><span><span> </span><span>+</span><span> ((String) obj).</span></span><span>length</span><span>());</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// Java 16+ 模式匹配版（免强转）</span></div></div><div><div><div>11</div></div><div><span>if</span><span> (obj </span><span>instanceof</span><span> </span><span>String</span><span> s) {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"长度: "</span><span><span> </span><span>+</span><span> </span></span><span>s</span><span>.</span><span>length</span><span>());</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>运算符优先级记忆<a href="#运算符优先级记忆"><span>#</span></a></h3><p><code>!</code> &gt; 算术 &gt; 比较 &gt; <code>&amp;</code> &gt; <code>^</code> &gt; <code>|</code> &gt; <code>&amp;&amp;</code> &gt; <code>||</code> &gt; 三元 &gt; 赋值。<strong>拿不准就加括号</strong>。</p></section></section>
<section><h2>五、输入与格式化输出<a href="#五输入与格式化输出"><span>#</span></a></h2><section><h3>Scanner 进阶<a href="#scanner-进阶"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Scanner</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Input</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>System</span><span>.</span><span>in</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"姓名: "</span><span>);</span></div></div><div><div><div>8</div></div><div><span>        </span><span>String</span><span><span> </span><span>name</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>next</span><span>();               </span><span>// 读一个词</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>sc</span><span>.</span><span>nextLine</span><span>();                          </span><span>// ⚠ 清掉残留换行（经典坑）</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"整行介绍: "</span><span>);</span></div></div><div><div><div>13</div></div><div><span>        </span><span>String</span><span><span> </span><span>intro</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextLine</span><span>();          </span><span>// 读整行</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"年龄: "</span><span>);</span></div></div><div><div><div>16</div></div><div><span>        </span><span>if</span><span> (</span><span>sc</span><span>.</span><span>hasNextInt</span><span>()) {                  </span><span>// 先判断再读（防崩）</span></div></div><div><div><div>17</div></div><div><span>            </span><span>int</span><span><span> </span><span>age</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextInt</span><span>();</span></div></div><div><div><div>18</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%s，%d岁%n"</span><span>, name, age);</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>20</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"年龄必须是数字"</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"成绩(double): "</span><span>);</span></div></div><div><div><div>24</div></div><div><span>        </span><span>double</span><span><span> </span><span>score</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextDouble</span><span>();</span></div></div><div><div><div>25</div></div><div><span>        </span><span>sc</span><span>.</span><span>close</span><span>();</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>next 与 nextLine 混用坑</strong>：<code>nextInt()</code> 不消耗行尾换行符，之后紧跟 <code>nextLine()</code> 会读到空串——中间补一次 <code>sc.nextLine()</code> 冲掉。</p></section><section><h3>printf 格式化<a href="#printf-格式化"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>double</span><span> price </span><span><span>=</span><span> </span></span><span>9.87654</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>42</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"两位小数: %.2f%n"</span><span><span>, price);</span><span>     </span></span><span>// 9.88</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"宽度10右对齐: [%10.2f]%n"</span><span>, price);</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"宽度10左对齐: [%-10.2f]%n"</span><span>, price);</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"补零: %08d%n"</span><span><span>, n);</span><span>             </span></span><span>// 00000042</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"千分位: %,d%n"</span><span>, </span><span>1234567890</span><span><span>);</span><span>   </span></span><span>// 1,234,567,890</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"百分比: %.1f%%%n"</span><span>, </span><span>0.856</span><span><span>);</span><span>     </span></span><span>// 85.6%</span></div></div><div><div><div>10</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"类型: %s / %d / %b / %c%n"</span><span>, </span><span>"文本"</span><span>, </span><span>1</span><span>, </span><span>true</span><span>, </span><span>'A'</span><span>);</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// %n 是跨平台换行符；String.format 同款语法返回字符串</span></div></div><div><div><div>13</div></div><div><span>String</span><span> s </span><span><span>=</span><span> </span></span><span>String</span><span>.</span><span>format</span><span>(</span><span>"排名 No.%03d"</span><span>, </span><span>7</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Math 工具类<a href="#math-工具类"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>abs</span><span><span>(</span><span>-</span></span><span>5</span><span><span>));</span><span>       </span></span><span>// 5</span></div></div><div><div><div>2</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>max</span><span>(</span><span>3</span><span>, </span><span>7</span><span><span>));</span><span>     </span></span><span>// 7</span></div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>min</span><span>(</span><span>3</span><span>, </span><span>7</span><span><span>));</span><span>     </span></span><span>// 3</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>sqrt</span><span>(</span><span>16</span><span><span>));</span><span>      </span></span><span>// 4.0</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>pow</span><span>(</span><span>2</span><span>, </span><span>10</span><span><span>));</span><span>    </span></span><span>// 1024.0</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>round</span><span>(</span><span>3.5</span><span><span>));</span><span>    </span></span><span>// 4（四舍五入，区别于强转截断）</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>ceil</span><span>(</span><span>3.1</span><span><span>));</span><span>     </span></span><span>// 4.0 向上</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>floor</span><span>(</span><span>3.9</span><span><span>));</span><span>    </span></span><span>// 3.0 向下</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Math</span><span>.</span><span>random</span><span><span>());</span><span>      </span></span><span>// [0,1) 随机</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、典型陷阱速查<a href="#六典型陷阱速查"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 整数除法</span></div></div><div><div><div>2</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>((</span><span>1</span><span><span> </span><span>+</span><span> </span></span><span>2</span><span><span>) </span><span>/</span><span> </span></span><span>2</span><span><span>);</span><span>        </span></span><span>// 1 不是 1.5</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 2. char 参与算术</span></div></div><div><div><div>5</div></div><div><span>char</span><span> c </span><span><span>=</span><span> </span></span><span>'A'</span><span>;</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(c </span><span>+</span><span> </span></span><span>1</span><span><span>);</span><span>              </span></span><span>// 66（int）</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>((</span><span>char</span><span><span>)(c </span><span>+</span><span> </span></span><span>1</span><span><span>));</span><span>      </span></span><span>// B</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 3. = 与 ==（编译器会拦大部分，但 boolean 变量场景要小心）</span></div></div><div><div><div>10</div></div><div><span>boolean</span><span> done </span><span><span>=</span><span> </span></span><span>false</span><span>;</span></div></div><div><div><div>11</div></div><div><span>if</span><span><span> (done </span><span>=</span><span> </span></span><span>true</span><span>) { }                    </span><span>// ⚠ 合法但几乎必是 bug</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 4. 负数取模</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(</span><span>-</span></span><span>10</span><span><span> </span><span>%</span><span> </span></span><span>3</span><span><span>);</span><span>            </span></span><span>// -1（跟被除数）</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// 5. float 精度（金额别用 float/double！）</span></div></div><div><div><div>17</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>0.1</span><span><span> </span><span>+</span><span> </span></span><span>0.2</span><span><span> </span><span>==</span><span> </span></span><span>0.3</span><span><span>);</span><span>   </span></span><span>// false</span></div></div><div><div><div>18</div></div><div><span>// 金额用 long 存"分"，或 java.math.BigDecimal</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>输入三角形三边，用海伦公式输出面积（保留 2 位小数，注意整数转 double）</li>
<li>输入秒数，格式化输出 <code>X天X小时X分X秒</code></li>
<li>验证 <code>(char)('a' + 3)</code> 输出什么？写循环打印 a-z（<code>char</code> 与 <code>int</code> 的关系）</li>
<li>用位运算判断整数奇偶、交换两个 int（不用第三变量）</li>
<li><code>int</code> 逆序输出各位数字（12345 → 5 4 3 2 1；循环 + % /）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>八大基本类型大小跨平台固定；整数字面量默认 int、小数默认 double</li>
<li><code>long</code> 加 L、<code>float</code> 加 f；<code>boolean</code> 不是整数</li>
<li>自动转换小→大；强转大→小会截断；两个 int 相除必得 int</li>
<li><code>&amp;&amp;</code>/<code>||</code> 短路；<code>&gt;&gt;&gt;</code> 是 Java 特有逻辑右移</li>
<li>Scanner 的 next/nextLine 混用要清残留；printf 与 String.format 同语法</li>
<li>金额远离浮点——用 long 分或 BigDecimal</li>
</ul><p><strong>下一篇</strong>：流程控制——分支、循环与 Java 的 switch 表达式。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。类型转换的每个例子请上机验证，坑见一次胜过听十次。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-03/</id>
      <title type="text">Java 入门教程（三）：流程控制</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-03/"/>
      <summary type="text">完整讲解 Java 分支（if/switch 语句与 switch 表达式）、三种循环、break/continue 带标签跳转、嵌套循环经典练习（九九表/质数/图形/水仙花），覆盖 Java 14+ 增强 switch 新语法。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>Java 的流程控制与 C/C++ 同源，但更安全（编译器更严格），且 Java 14+ 引入了现代的 <strong>switch 表达式</strong>。本篇全覆盖，含经典练习。</p></section>
<section><h2>一、分支<a href="#一分支"><span>#</span></a></h2><section><h3>if / else if / else<a href="#if--else-if--else"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Scanner</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Grade</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>System</span><span>.</span><span>in</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>int</span><span><span> </span><span>score</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextInt</span><span>();</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>        </span><span>if</span><span><span> (score </span><span>&gt;=</span><span> </span></span><span>90</span><span>) {</span></div></div><div><div><div>9</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"优秀"</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> </span><span>if</span><span><span> (score </span><span>&gt;=</span><span> </span></span><span>80</span><span>) {</span></div></div><div><div><div>11</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"良好"</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> </span><span>if</span><span><span> (score </span><span>&gt;=</span><span> </span></span><span>60</span><span>) {</span></div></div><div><div><div>13</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"及格"</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>15</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"不及格"</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>与 C++ 唯一显著差异：Java 条件必须是 <code>boolean</code>——<code>if (score = 90)</code> 这种笔误<strong>直接编译错误</strong>（比 C++ 安全）。</p></section><section><h3>传统 switch 语句<a href="#传统-switch-语句"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Calculator</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>char</span><span><span> </span><span>op</span><span> </span></span><span><span>=</span><span> </span></span><span>'+'</span><span>;</span></div></div><div><div><div>4</div></div><div><span>        </span><span>int</span><span><span> </span><span>a</span><span> </span></span><span><span>=</span><span> </span></span><span>3</span><span><span>, b </span><span>=</span><span> </span></span><span>4</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>        </span><span>switch</span><span> (op) {</span></div></div><div><div><div>7</div></div><div><span>            </span><span>case</span><span> </span><span>'+'</span><span>:</span></div></div><div><div><div>8</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>+</span><span> b);</span></span></div></div><div><div><div>9</div></div><div><span>                </span><span>break</span><span>;                          </span><span>// ⚠ 照样会贯穿！</span></div></div><div><div><div>10</div></div><div><span>            </span><span>case</span><span> </span><span>'-'</span><span>:</span></div></div><div><div><div>11</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>-</span><span> b);</span></span></div></div><div><div><div>12</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>13</div></div><div><span>            </span><span>case</span><span> </span><span>'*'</span><span>:</span></div></div><div><div><div>14</div></div><div><span>            </span><span>case</span><span> </span><span>'x'</span><span>:</span><span>                           </span><span>// 多标签共享分支</span></div></div><div><div><div>15</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>*</span><span> b);</span></span></div></div><div><div><div>16</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>17</div></div><div><span>            </span><span>default:</span></div></div><div><div><div>18</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"不支持"</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>switch 支持的类型：<code>byte/short/char/int</code>、<code>String</code>（Java 7+！）、枚举。<strong>不支持 long、double、float</strong>。</p></section><section><h3>switch 表达式（Java 14+，现代首选）<a href="#switch-表达式java-14现代首选"><span>#</span></a></h3><p>箭头语法：不贯穿、不用 break、可直接返回值：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Week</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>int</span><span><span> </span><span>day</span><span> </span></span><span><span>=</span><span> </span></span><span>6</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>        </span><span>// ① 箭头分支（无贯穿烦恼）</span></div></div><div><div><div>6</div></div><div><span>        </span><span>String</span><span><span> </span><span>type</span><span> </span></span><span><span>=</span><span> </span></span><span>switch</span><span> (day) {</span></div></div><div><div><div>7</div></div><div><span>            </span><span>case</span><span> </span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span> </span><span>-&gt;</span><span> </span><span>"工作日"</span><span>;</span></div></div><div><div><div>8</div></div><div><span>            </span><span>case</span><span> </span><span>6</span><span>, </span><span>7</span><span> </span><span>-&gt;</span><span> </span><span>"周末"</span><span>;</span></div></div><div><div><div>9</div></div><div><span>            </span><span>default</span><span> </span><span>-&gt;</span><span> </span><span>"非法日期"</span><span>;           </span><span>// 必须穷尽！有 default 才编译通过</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>};</span></div></div><div><div><div>11</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(type);            </span><span>// 周末</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>// ② 带代码块的分支（yield 返回值）</span></div></div><div><div><div>14</div></div><div><span>        </span><span>String</span><span><span> </span><span>detail</span><span> </span></span><span><span>=</span><span> </span></span><span>switch</span><span> (day) {</span></div></div><div><div><div>15</div></div><div><span>            </span><span>case</span><span> </span><span>6</span><span>, </span><span>7</span><span> </span><span>-&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span>                </span><span>String</span><span><span> </span><span>name</span><span> </span></span><span><span>=</span><span> (day </span><span>==</span><span> </span></span><span>6</span><span>) </span><span>?</span><span> </span><span>"周六"</span><span> </span><span>:</span><span> </span><span>"周日"</span><span>;</span></div></div><div><div><div>17</div></div><div><span>                </span><span>yield</span><span><span> name </span><span>+</span><span> </span></span><span>"休息"</span><span>;         </span><span>// yield 产出值</span></div></div><div><div><div>18</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>            </span><span>default</span><span> </span><span>-&gt;</span><span> </span><span>"上班"</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>};</span></div></div><div><div><div>21</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(detail);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>新语法三大优点</strong>：不贯穿、强制穷尽（编译器查漏）、能当表达式赋值。新代码一律用它。</p></section><section><h3>三元运算符<a href="#三元运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>10</span><span><span>,</span><span> b </span><span>=</span><span> </span></span><span>20</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> max </span><span><span>=</span><span> a </span><span>&gt;</span><span> b </span></span><span>?</span><span> a </span><span>:</span><span><span> b</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、循环<a href="#二循环"><span>#</span></a></h2><section><h3>while 与 do-while<a href="#while-与-do-while"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1~100 求和</span></div></div><div><div><div>2</div></div><div><span>int</span><span> sum </span><span><span>=</span><span> </span></span><span>0</span><span><span>,</span><span> i </span><span>=</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>while</span><span><span> (i </span><span>&lt;=</span><span> </span></span><span>100</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>sum </span><span>+=</span><span> i</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>i</span><span>++;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(sum);</span><span>      </span></span><span>// 5050</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// do-while：至少执行一次（菜单场景）</span></div></div><div><div><div>10</div></div><div><span>int</span><span> choice</span><span>;</span></div></div><div><div><div>11</div></div><div><span>do</span><span> {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"1.开始 0.退出"</span><span>);</span></div></div><div><div><div>13</div></div><div><span>    </span><span>// choice = 读入...</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>choice </span><span>=</span><span> </span><span>0</span><span><span>;</span><span>               </span></span><span>// 演示用</span></div></div><div><div><div>15</div></div><div><span>} </span><span>while</span><span><span> (choice </span><span>!=</span><span> </span></span><span>0</span><span><span>)</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>for 经典三段式<a href="#for-经典三段式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>1</span><span><span>;</span><span> i </span><span>&lt;=</span><span> </span></span><span>9</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%d "</span><span><span>, i </span><span>*</span><span> i);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 多变量版本</span></div></div><div><div><div>6</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>,</span><span> j </span><span>=</span><span> </span></span><span>10</span><span><span>;</span><span> i </span><span>&lt;</span><span> j</span><span>;</span><span> i</span><span>++,</span><span> j</span><span>--</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(i </span><span>+</span><span> </span></span><span>" "</span><span><span> </span><span>+</span><span> j);</span></span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 死循环</span></div></div><div><div><div>11</div></div><div><span>for</span><span><span> (</span><span>;;</span><span>) { }</span></span></div></div><div><div><div>12</div></div><div><span>while</span><span> (</span><span>true</span><span>) { }</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>增强 for（for-each）：遍历数组/集合<a href="#增强-forfor-each遍历数组集合"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span>[] nums </span><span><span>=</span><span> {</span></span><span>10</span><span><span>,</span><span> </span></span><span>20</span><span><span>,</span><span> </span></span><span>30</span><span><span>}</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> n </span><span>:</span><span> nums) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(n);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>String</span><span>[] langs </span><span><span>=</span><span> {</span></span><span>"Java"</span><span><span>,</span><span> </span></span><span>"Python"</span><span><span>,</span><span> </span></span><span>"C++"</span><span><span>}</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>for</span><span> (</span><span>String</span><span> lang </span><span>:</span><span> langs) {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(lang);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>限制</strong>：拿不到下标、遍历中不能修改数组元素（只读便利）。</p></section></section>
<section><h2>三、break / continue 与标签<a href="#三break--continue-与标签"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 常规：作用于本层</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>10</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> (i </span><span>==</span><span> </span></span><span>5</span><span>) </span><span>break</span><span><span>;</span><span>            </span></span><span>// 0~4</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> (i </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>) </span><span>continue</span><span><span>;</span><span>     </span></span><span>// 跳过偶数</span></div></div><div><div><div>5</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(i);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// Java 特色：标签跳转（直接跳出多层循环，goto 的安全版）</span></div></div><div><div><div>9</div></div><div><span>outer</span><span>:</span></div></div><div><div><div>10</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>1</span><span><span>;</span><span> i </span><span>&lt;=</span><span> </span></span><span>9</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> j </span><span><span>=</span><span> </span></span><span>1</span><span><span>;</span><span> j </span><span>&lt;=</span><span> </span></span><span>9</span><span><span>;</span><span> j</span><span>++</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span><span> (i </span><span>*</span><span> j </span><span>&gt;</span><span> </span></span><span>30</span><span>) {</span></div></div><div><div><div>13</div></div><div><span>            </span><span>break</span><span><span> outer</span><span>;</span><span>          </span></span><span>// 一口气跳出两层！</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%d×%d=%d "</span><span><span>, i, j, i </span><span>*</span><span> j);</span></span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>();</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>// continue outer：跳到外层下一轮</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>标签语法是 Java 对”多层循环跳出”的正规解（C++ 只能用标志变量或 goto）。</p></section>
<section><h2>四、经典练习<a href="#四经典练习"><span>#</span></a></h2><section><h3>1. 九九乘法表<a href="#1-九九乘法表"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>1</span><span><span>;</span><span> i </span><span>&lt;=</span><span> </span></span><span>9</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> j </span><span><span>=</span><span> </span></span><span>1</span><span><span>;</span><span> j </span><span>&lt;=</span><span> i</span><span>;</span><span> j</span><span>++</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%d×%d=%-4d"</span><span><span>, j, i, i </span><span>*</span><span> j);</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>();</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 质数判断与 100 内质数表<a href="#2-质数判断与-100-内质数表"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>static</span><span> </span><span>boolean</span><span> </span><span>isPrime</span><span>(</span><span>int</span><span> n) {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span><span> (n </span><span>&lt;</span><span> </span></span><span>2</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>2</span><span><span>;</span><span> (</span></span><span>long</span><span><span>) i </span><span>*</span><span> i </span><span>&lt;=</span><span> n</span><span>;</span><span> i</span><span>++</span><span>) {    </span></span><span>// i*i 防溢出用 long 比</span></div></div><div><div><div>4</div></div><div><span>        </span><span>if</span><span><span> (n </span><span>%</span><span> i </span><span>==</span><span> </span></span><span>0</span><span>) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span>[] args) {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>int</span><span> count </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>2</span><span><span>;</span><span> n </span><span>&lt;</span><span> </span></span><span>100</span><span><span>;</span><span> n</span><span>++</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span> (</span><span>isPrime</span><span>(n)) {</span></div></div><div><div><div>13</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%d "</span><span>, n);</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>count</span><span>++;</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"</span><span>\n</span><span>共 "</span><span><span> </span><span>+</span><span> count </span><span>+</span><span> </span></span><span>" 个"</span><span>);</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>3. 水仙花数<a href="#3-水仙花数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>100</span><span><span>;</span><span> n </span><span>&lt;</span><span> </span></span><span>1000</span><span><span>;</span><span> n</span><span>++</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span> a </span><span><span>=</span><span> n </span><span>/</span><span> </span></span><span>100</span><span><span>,</span><span> b </span><span>=</span><span> n </span><span>/</span><span> </span></span><span>10</span><span><span> </span><span>%</span><span> </span></span><span>10</span><span><span>,</span><span> c </span><span>=</span><span> n </span><span>%</span><span> </span></span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> (a</span><span>*</span><span>a</span><span>*</span><span>a </span><span>+</span><span> b</span><span>*</span><span>b</span><span>*</span><span>b </span><span>+</span><span> c</span><span>*</span><span>c</span><span>*</span><span>c </span><span>==</span><span> n)</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(n);</span><span>       </span></span><span>// 153 370 371 407</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 菱形图案（嵌套循环的空间训练）<a href="#4-菱形图案嵌套循环的空间训练"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>5</span><span><span>;</span><span>    </span></span><span>// 菱形半径</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span><span>-</span><span>n</span><span>;</span><span> i </span><span>&lt;=</span><span> n</span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> row </span><span><span>=</span><span> n </span><span>-</span><span> </span></span><span>Math</span><span>.</span><span>abs</span><span><span>(i);</span><span>           </span></span><span>// 当前行星数半径</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> s </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> s </span><span>&lt;</span><span> </span></span><span>Math</span><span>.</span><span>abs</span><span><span>(i);</span><span> s</span><span>++</span><span>) </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>" "</span><span>);</span></div></div><div><div><div>5</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> j </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> j </span><span>&lt;</span><span> </span></span><span>2</span><span><span> </span><span>*</span><span> row </span><span>+</span><span> </span></span><span>1</span><span><span>;</span><span> j</span><span>++</span><span>) </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"*"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>();</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>5. 猜数字（输入校验 + 循环）<a href="#5-猜数字输入校验--循环"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Random</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.Scanner</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Guess</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>Random</span><span><span> </span><span>rand</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Random</span><span>();</span></div></div><div><div><div>7</div></div><div><span>        </span><span>int</span><span><span> </span><span>answer</span><span> </span></span><span><span>=</span><span> </span></span><span>rand</span><span>.</span><span>nextInt</span><span>(</span><span>100</span><span><span>) </span><span>+</span><span> </span></span><span>1</span><span>;     </span><span>// 1~100</span></div></div><div><div><div>8</div></div><div><span>        </span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>System</span><span>.</span><span>in</span><span>);</span></div></div><div><div><div>9</div></div><div><span>        </span><span>int</span><span><span> </span><span>tries</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>while</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>12</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"猜(1-100): "</span><span>);</span></div></div><div><div><div>13</div></div><div><span>            </span><span>if</span><span><span> (</span><span>!</span></span><span>sc</span><span>.</span><span>hasNextInt</span><span>()) {             </span><span>// 输入校验</span></div></div><div><div><div>14</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"请输入数字！"</span><span><span> </span><span>+</span><span> </span></span><span>sc</span><span>.</span><span>next</span><span><span>() </span><span>+</span><span> </span></span><span>" 被忽略"</span><span>);</span></div></div><div><div><div>15</div></div><div><span>                </span><span>continue</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>            </span><span>int</span><span><span> </span><span>guess</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextInt</span><span>();</span></div></div><div><div><div>18</div></div><div><span><span>            </span></span><span>tries++;</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>            </span><span>if</span><span><span> (guess </span><span>&lt;</span><span> answer)      </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"小了"</span><span>);</span></div></div><div><div><div>21</div></div><div><span>            </span><span>else</span><span> </span><span>if</span><span><span> (guess </span><span>&gt;</span><span> answer) </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"大了"</span><span>);</span></div></div><div><div><div>22</div></div><div><span>            </span><span>else</span><span> {</span></div></div><div><div><div>23</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"对了！用了 "</span><span><span> </span><span>+</span><span> tries </span><span>+</span><span> </span></span><span>" 次"</span><span>);</span></div></div><div><div><div>24</div></div><div><span>                </span><span>break</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>五、产生随机数的方式<a href="#五产生随机数的方式"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 方式1：Random 类（推荐）</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.Random</span><span>;</span></div></div><div><div><div>3</div></div><div><span>Random</span><span> rand </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Random</span><span><span>()</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>rand</span><span>.</span><span>nextInt</span><span>(</span><span>100</span><span><span>)</span><span> </span><span>+</span><span> </span></span><span>1</span><span><span>;</span><span>       </span></span><span>// 1~100</span></div></div><div><div><div>5</div></div><div><span>double</span><span> d </span><span><span>=</span><span> </span></span><span>rand</span><span>.</span><span>nextDouble</span><span><span>();</span><span>         </span></span><span>// [0,1)</span></div></div><div><div><div>6</div></div><div><span>boolean</span><span> b </span><span><span>=</span><span> </span></span><span>rand</span><span>.</span><span>nextBoolean</span><span>();</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 方式2：Math.random()</span></div></div><div><div><div>9</div></div><div><span>int</span><span> m </span><span><span>=</span><span> (</span></span><span>int</span><span>)(</span><span>Math</span><span>.</span><span>random</span><span><span>()</span><span> </span><span>*</span><span> </span></span><span>100</span><span><span>) </span><span>+</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 固定种子 → 可复现（测试用）</span></div></div><div><div><div>12</div></div><div><span>Random</span><span> seeded </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Random</span><span>(</span><span>42</span><span><span>)</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>输入一个整数，判断是否为回文数（12321 ✓；循环反转数字后比较）</li>
<li>求 1000 内所有”完数”（因子和等于自身，如 6=1+2+3）</li>
<li>用 switch 表达式输出某年某月的天数（注意闰年二月：<code>(y%4==0&amp;&amp;y%100!=0)||y%400==0</code>）</li>
<li>打印斐波那契数列前 20 项（for + 两个变量滚动）</li>
<li>二重循环求”3 个数字组合能组成多少个互不相同的三位数”（1、2、3、4）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>条件必须 boolean（if 笔误编译期拦截）；switch 支持 String 与枚举</li>
<li>switch 表达式（Java 14+）：箭头不贯穿、强制穷尽、可赋值——新代码首选</li>
<li>增强 for 遍历数组简洁但无下标</li>
<li>标签 break/continue 可直接跳出多层循环</li>
<li>hasNextInt 先验后读防输入崩溃</li>
</ul><p><strong>下一篇</strong>：方法与数组——Java 版的函数与第一批容器。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。五个经典练习独立完成后再看参考，效果翻倍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-04/</id>
      <title type="text">Java 入门教程（四）：方法与数组</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-04/"/>
      <summary type="text">掌握 Java 方法定义与重载、可变参数、值传递本质、数组全操作（声明/遍历/工具类 Arrays/二维数组）、命令行参数与 main 签名，附数组统计与矩阵转置实战。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>Java 的函数叫<strong>方法</strong>（method），必须定义在类里；数组是 Java 最原始的容器。本篇讲透两者的规则与工具，为面向对象做准备。</p></section>
<section><h2>一、方法<a href="#一方法"><span>#</span></a></h2><section><h3>基本结构<a href="#基本结构"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>MathUtils</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>    </span><span>// 修饰符 返回类型 方法名(参数列表)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span> </span><span>add</span><span>(</span><span>int</span><span><span> </span><span>a</span><span>, </span></span><span>int</span><span><span> </span><span>b</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span><span> a </span><span>+</span><span> b;</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>// 无返回值用 void</span></div></div><div><div><div>9</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>printLine</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>i</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span><span>; i </span><span>&lt;</span><span> n; i++) </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"-"</span><span>);</span></div></div><div><div><div>11</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>();</span></div></div><div><div><div>12</div></div><div><span>        </span><span>// void 方法可单独 return 提前结束</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>16</div></div><div><span>        </span><span>int</span><span><span> </span><span>sum</span><span> </span></span><span><span>=</span><span> </span></span><span>add</span><span>(</span><span>3</span><span>, </span><span>4</span><span>);          </span><span>// 类内调用静态方法可省类名</span></div></div><div><div><div>17</div></div><div><span>        </span><span>MathUtils</span><span>.</span><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>18</div></div><div><span>        </span><span>printLine</span><span>(</span><span>20</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>方法签名 = 方法名 + 参数列表</strong>（返回值不算）。<code>static</code> 意义在面向对象篇详讲，本系列目前统一加。</p></section><section><h3>值传递的本质（重要！）<a href="#值传递的本质重要"><span>#</span></a></h3><p>Java <strong>只有值传递</strong>——传基本类型是拷贝值，传引用类型是拷贝”地址值”：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>static</span><span> </span><span>void</span><span> </span><span>tryChange</span><span>(</span><span>int</span><span><span> x) { x </span><span>=</span><span> </span></span><span>100</span><span><span>;</span><span> }              </span></span><span>// 改副本，无效</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>static</span><span> </span><span>void</span><span> </span><span>changeElement</span><span>(</span><span>int</span><span>[] arr) { arr[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>100</span><span><span>;</span><span> } </span></span><span>// 通过地址改内容，有效！</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>static</span><span> </span><span>void</span><span> </span><span>changeRef</span><span>(</span><span>int</span><span><span>[] arr) { arr </span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[]{</span><span>9</span><span><span>}</span><span>;</span><span> } </span></span><span>// 改的是地址副本，无效</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span>[] args) {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>5</span><span>;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>tryChange</span><span><span>(n)</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(n);</span><span>        </span></span><span>// 5</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>int</span><span>[] a </span><span><span>=</span><span> {</span></span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>,</span><span> </span></span><span>3</span><span><span>}</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span>    </span><span>changeElement</span><span><span>(a)</span><span>;</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(a[</span><span>0</span><span><span>]);</span><span>     </span></span><span>// 100（内容被改）</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>int</span><span>[] b </span><span><span>=</span><span> {</span></span><span>1</span><span><span>}</span><span>;</span></span></div></div><div><div><div>17</div></div><div><span>    </span><span>changeRef</span><span><span>(b)</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(b[</span><span>0</span><span><span>]);</span><span>     </span></span><span>// 1（b 还是指向原数组）</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>类比</strong>：引用类型传的是”门牌号复印件”——拿着复印件能进屋搬东西（改内容），但把复印件改成新地址不影响你手里的原件（改指向）。</p></section><section><h3>重载（Overload）<a href="#重载overload"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span>    </span><span>max</span><span>(</span><span>int</span><span><span> a</span><span>,</span><span> </span></span><span>int</span><span> b)          { </span><span>return</span><span><span> a </span><span>&gt;</span><span> b </span></span><span>?</span><span> a </span><span>:</span><span><span> b</span><span>;</span><span> }</span></span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>double</span><span> </span><span>max</span><span>(</span><span>double</span><span><span> a</span><span>,</span><span> </span></span><span>double</span><span> b)    { </span><span>return</span><span><span> a </span><span>&gt;</span><span> b </span></span><span>?</span><span> a </span><span>:</span><span><span> b</span><span>;</span><span> }</span></span></div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span>    </span><span>max</span><span>(</span><span>int</span><span><span> a</span><span>,</span><span> </span></span><span>int</span><span><span> b</span><span>,</span><span> </span></span><span>int</span><span> c)   { </span><span>return</span><span> </span><span>max</span><span>(</span><span>max</span><span><span>(a</span><span>,</span><span> b)</span><span>,</span><span> c)</span><span>;</span><span> }</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>max</span><span>(</span><span>3</span><span><span>,</span><span> </span></span><span>7</span><span><span>)</span><span>;</span><span>          </span></span><span>// int 版</span></div></div><div><div><div>6</div></div><div><span>max</span><span>(</span><span>3.5</span><span><span>,</span><span> </span></span><span>2.5</span><span><span>)</span><span>;</span><span>      </span></span><span>// double 版</span></div></div><div><div><div>7</div></div><div><span>max</span><span>(</span><span>1</span><span><span>,</span><span> </span></span><span>9</span><span><span>,</span><span> </span></span><span>4</span><span><span>)</span><span>;</span><span>       </span></span><span>// 三参版</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重载规则：参数个数/类型/顺序不同即可；<strong>仅返回值不同不行</strong>。JDK 的 <code>System.out.println</code> 有 10 个重载——这就是重载的日常。</p></section><section><h3>可变参数（varargs）<a href="#可变参数varargs"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 类型... 名字 = 语法糖，本质是数组</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span> </span><span>sum</span><span>(</span><span>int</span><span><span>...</span><span> </span></span><span>nums</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> total </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> n </span><span>:</span><span><span> nums) total </span><span>+=</span><span> n</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span><span> total</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>sum</span><span><span>()</span><span>;</span><span>              </span></span><span>// 0</span></div></div><div><div><div>9</div></div><div><span>sum</span><span>(</span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>)</span><span>;</span><span>          </span></span><span>// 3</span></div></div><div><div><div>10</div></div><div><span>sum</span><span>(</span><span>new</span><span> </span><span>int</span><span>[]{</span><span>1</span><span>,</span><span>2</span><span>,</span><span>3</span><span><span>})</span><span>;</span><span>  </span></span><span>// 6（直接传数组也行）</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// ⚠ 可变参数必须是最后一个参数</span></div></div><div><div><div>13</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>log</span><span>(</span><span>String</span><span><span> level</span><span>,</span><span> </span></span><span>Object</span><span><span>...</span><span> </span></span><span>args</span><span>) { }</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>方法递归<a href="#方法递归"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>long</span><span> </span><span>factorial</span><span>(</span><span>int</span><span> n) {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span><span> (n </span><span>&lt;=</span><span> </span></span><span>1</span><span>) </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span><span> n </span><span>*</span><span> </span></span><span>factorial</span><span><span>(n </span><span>-</span><span> </span></span><span>1</span><span><span>)</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>// factorial(20) 已接近 long 上限（选对类型！）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、数组<a href="#二数组"><span>#</span></a></h2><section><h3>声明与初始化<a href="#声明与初始化"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 静态初始化（定长不可变！）</span></div></div><div><div><div>2</div></div><div><span>int</span><span>[] scores </span><span><span>=</span><span> {</span></span><span>90</span><span><span>,</span><span> </span></span><span>85</span><span><span>,</span><span> </span></span><span>78</span><span><span>,</span><span> </span></span><span>92</span><span><span>,</span><span> </span></span><span>66</span><span><span>}</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>int</span><span>[] primes </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[]{</span><span>2</span><span><span>,</span><span> </span></span><span>3</span><span><span>,</span><span> </span></span><span>5</span><span><span>,</span><span> </span></span><span>7</span><span><span>}</span><span>;</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 动态初始化（定容，默认值填充）</span></div></div><div><div><div>6</div></div><div><span>int</span><span>[] nums </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>5</span><span><span>]</span><span>;</span><span>          </span></span><span>// {0,0,0,0,0}</span></div></div><div><div><div>7</div></div><div><span>String</span><span>[] names </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>String</span><span>[</span><span>3</span><span><span>]</span><span>;</span><span>   </span></span><span>// {null, null, null}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 长度是属性（不是方法！）</span></div></div><div><div><div>10</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>scores</span><span>.</span><span>length</span><span><span>);</span><span>    </span></span><span>// 5</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// C 风格声明 int scores[] 也合法，但不推荐</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>Java 数组<strong>长度固定</strong>、越界访问抛 <code>ArrayIndexOutOfBoundsException</code>（运行期异常，比 C++ 裸数组安全）。要动态长度用 <code>ArrayList</code>（第六篇集合）。</p></div></div></section><section><h3>遍历三式<a href="#遍历三式"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span>[] v </span><span><span>=</span><span> {</span></span><span>3</span><span><span>,</span><span> </span></span><span>1</span><span><span>,</span><span> </span></span><span>4</span><span><span>,</span><span> </span></span><span>1</span><span><span>,</span><span> </span></span><span>5</span><span><span>}</span><span>;</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// ① 经典下标</span></div></div><div><div><div>4</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>v</span><span>.</span><span>length</span><span><span>;</span><span> i</span><span>++</span><span>)</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(i </span><span>+</span><span> </span></span><span>": "</span><span><span> </span><span>+</span><span> v[i]);</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// ② 增强 for</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>int</span><span> n </span><span>:</span><span> v)</span></div></div><div><div><div>9</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(n);</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// ③ 带索引的函数式（Java 8+，尝鲜）</span></div></div><div><div><div>12</div></div><div><span>java</span><span>.</span><span>util</span><span>.</span><span>Arrays</span><span>.</span><span>stream</span><span>(v)</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>.</span><span>forEach</span><span>(n </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(n));</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>// 求 max/min/sum</span></div></div><div><div><div>16</div></div><div><span>int</span><span> max </span><span><span>=</span><span> v[</span></span><span>0</span><span><span>]</span><span>;</span></span></div></div><div><div><div>17</div></div><div><span>for</span><span> (</span><span>int</span><span> n </span><span>:</span><span> v) </span><span>if</span><span><span> (n </span><span>&gt;</span><span> max) max </span><span>=</span><span> n</span><span>;</span></span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>int</span><span> sum </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>20</div></div><div><span>for</span><span> (</span><span>int</span><span> n </span><span>:</span><span><span> v) sum </span><span>+=</span><span> n</span><span>;</span></span></div></div><div><div><div>21</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"max=%d avg=%.1f%n"</span><span><span>, max, sum </span><span>/</span><span> (</span></span><span>double</span><span>) </span><span>v</span><span>.</span><span>length</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>数组工具类 java.util.Arrays（必备！）<a href="#数组工具类-javautilarrays必备"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Arrays</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span>[] v </span><span><span>=</span><span> {</span></span><span>5</span><span><span>,</span><span> </span></span><span>3</span><span><span>,</span><span> </span></span><span>8</span><span><span>,</span><span> </span></span><span>1</span><span><span>,</span><span> </span></span><span>9</span><span><span>}</span><span>;</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 打印（toString 解决"打印数组显示乱码地址"问题）</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Arrays</span><span>.</span><span>toString</span><span><span>(v));</span><span>   </span></span><span>// [5, 3, 8, 1, 9]</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 排序（原地）</span></div></div><div><div><div>9</div></div><div><span>Arrays</span><span>.</span><span>sort</span><span><span>(v);</span><span>                            </span></span><span>// [1, 3, 5, 8, 9]</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 查找（必须先有序！返回下标，-1 = 没找到）</span></div></div><div><div><div>12</div></div><div><span>int</span><span> idx </span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>binarySearch</span><span>(v, </span><span>8</span><span><span>);</span><span>       </span></span><span>// 3</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 填充</span></div></div><div><div><div>15</div></div><div><span>int</span><span>[] filled </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>5</span><span><span>]</span><span>;</span></span></div></div><div><div><div>16</div></div><div><span>Arrays</span><span>.</span><span>fill</span><span>(filled, </span><span>7</span><span><span>);</span><span>                    </span></span><span>// [7,7,7,7,7]</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>// 拷贝（真正的复制，不是引用）</span></div></div><div><div><div>19</div></div><div><span>int</span><span>[] copy </span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>copyOf</span><span>(v, </span><span>v</span><span>.</span><span>length</span><span>);</span></div></div><div><div><div>20</div></div><div><span>int</span><span>[] part </span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>copyOfRange</span><span>(v, </span><span>1</span><span>, </span><span>4</span><span><span>);</span><span>  </span></span><span>// 下标 [1,4) 的子数组</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>// 比较（内容比较，== 比较的是地址！）</span></div></div><div><div><div>23</div></div><div><span>int</span><span>[] a </span><span><span>=</span><span> {</span></span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>}</span><span>;</span></span></div></div><div><div><div>24</div></div><div><span>int</span><span>[] b </span><span><span>=</span><span> {</span></span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>}</span><span>;</span></span></div></div><div><div><div>25</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> b);</span><span>                    </span></span><span>// false（两个对象）</span></div></div><div><div><div>26</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Arrays</span><span>.</span><span>equals</span><span><span>(a, b));</span><span>       </span></span><span>// true（内容相等）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>二维数组<a href="#二维数组"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span>[][] matrix </span><span><span>=</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>{</span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>,</span><span> </span></span><span>3</span><span><span>}</span><span>,</span></span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>{</span><span>4</span><span><span>,</span><span> </span></span><span>5</span><span><span>,</span><span> </span></span><span>6</span><span><span>}</span><span>,</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>{</span><span>7</span><span><span>,</span><span> </span></span><span>8</span><span><span>,</span><span> </span></span><span>9</span><span><span>}</span><span>,</span></span></div></div><div><div><div>5</div></div><div><span><span>}</span><span>;</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>matrix</span><span>.</span><span>length</span><span><span>);</span><span>       </span></span><span>// 3（行数）</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(matrix[</span><span>0</span><span>].</span><span>length</span><span><span>);</span><span>    </span></span><span>// 3（列数）</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 遍历求和</span></div></div><div><div><div>11</div></div><div><span>int</span><span> total </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>12</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>matrix</span><span>.</span><span>length</span><span><span>;</span><span> i</span><span>++</span><span>)</span></span></div></div><div><div><div>13</div></div><div><span>    </span><span>for</span><span> (</span><span>int</span><span> j </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> j </span><span>&lt;</span><span> matrix[i]</span><span>.</span></span><span>length</span><span><span>;</span><span> j</span><span>++</span><span>)</span></span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>total </span><span>+=</span><span> matrix[i][j]</span><span>;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// 不规则数组（每行长度可以不同——Java 数组本质是"数组的数组"）</span></div></div><div><div><div>17</div></div><div><span>int</span><span>[][] ragged </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>3</span><span><span>][]</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>ragged[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>1</span><span><span>]</span><span>;</span></span></div></div><div><div><div>19</div></div><div><span>ragged[</span><span>1</span><span><span>] </span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>2</span><span><span>]</span><span>;</span></span></div></div><div><div><div>20</div></div><div><span>ragged[</span><span>2</span><span><span>] </span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[</span><span>3</span><span><span>]</span><span>;</span></span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>// 打印二维：deepToString</span></div></div><div><div><div>23</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Arrays</span><span>.</span><span>deepToString</span><span>(matrix));</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>main 的 String[] args<a href="#main-的-string-args"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ArgsDemo</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>// java ArgsDemo hello 42</span></div></div><div><div><div>4</div></div><div><span>        </span><span>for</span><span> (</span><span>String</span><span><span> </span><span>arg</span><span> </span></span><span>:</span><span> args)</span></div></div><div><div><div>5</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(arg);       </span><span>// hello \n 42</span></div></div><div><div><div>6</div></div><div><span>        </span><span>// args 是命令行参数数组（不含类名）</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、综合实战<a href="#三综合实战"><span>#</span></a></h2><section><h3>1. 数组统计分析器<a href="#1-数组统计分析器"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Arrays</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ScoreAnalyzer</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>max</span><span>(</span><span>int</span><span><span>[] </span><span>a</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>int</span><span><span> </span><span>m</span><span> </span></span><span><span>=</span><span> a[</span></span><span>0</span><span>];</span></div></div><div><div><div>6</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>x</span><span> </span></span><span>:</span><span> a) </span><span>if</span><span><span> (x </span><span>&gt;</span><span> m) m </span><span>=</span><span> x;</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>return</span><span> m;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>static</span><span> </span><span>double</span><span> </span><span>average</span><span>(</span><span>int</span><span><span>[] </span><span>a</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>int</span><span><span> </span><span>s</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>12</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>x</span><span> </span></span><span>:</span><span><span> a) s </span><span>+=</span><span> x;</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>return</span><span><span> s </span><span>/</span><span> (</span></span><span>double</span><span>) </span><span>a</span><span>.</span><span>length</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>17</div></div><div><span>        </span><span>int</span><span><span>[] </span><span>scores</span><span> </span></span><span><span>=</span><span> {</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>, </span><span>88</span><span>, </span><span>73</span><span>};</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>        </span><span>int</span><span><span>[] </span><span>sorted</span><span> </span></span><span><span>=</span><span> </span></span><span>scores</span><span>.</span><span>clone</span><span>();         </span><span>// 复制后排，不破坏原序</span></div></div><div><div><div>20</div></div><div><span>        </span><span>Arrays</span><span>.</span><span>sort</span><span>(sorted);</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"原始: "</span><span><span> </span><span>+</span><span> </span></span><span>Arrays</span><span>.</span><span>toString</span><span>(scores));</span></div></div><div><div><div>23</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"排序: "</span><span><span> </span><span>+</span><span> </span></span><span>Arrays</span><span>.</span><span>toString</span><span>(sorted));</span></div></div><div><div><div>24</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"最高 %d 最低 %d 平均 %.1f%n"</span><span>,</span></div></div><div><div><div>25</div></div><div><span>                </span><span>max</span><span>(scores), sorted[</span><span>0</span><span>], </span><span>average</span><span>(scores));</span></div></div><div><div><div>26</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"中位数: "</span><span><span> </span><span>+</span></span></div></div><div><div><div>27</div></div><div><span><span>                </span></span><span>(</span><span>sorted</span><span>.</span><span>length</span><span><span> </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>1</span></div></div><div><div><div>28</div></div><div><span>                    </span><span>?</span><span> sorted[</span><span>sorted</span><span>.</span><span>length</span><span><span> </span><span>/</span><span> </span></span><span>2</span><span>]</span></div></div><div><div><div>29</div></div><div><span>                    </span><span>:</span><span> (sorted[</span><span>sorted</span><span>.</span><span>length</span><span>/</span><span>2</span><span><span> </span><span>-</span><span> </span></span><span>1</span><span><span>] </span><span>+</span><span> sorted[</span></span><span>sorted</span><span>.</span><span>length</span><span>/</span><span>2</span><span><span>]) </span><span>/</span><span> </span></span><span>2.0</span><span>));</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>        </span><span>// 高于平均分的比例</span></div></div><div><div><div>32</div></div><div><span>        </span><span>double</span><span><span> </span><span>avg</span><span> </span></span><span><span>=</span><span> </span></span><span>average</span><span>(scores);</span></div></div><div><div><div>33</div></div><div><span>        </span><span>long</span><span><span> </span><span>above</span><span> </span></span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>stream</span><span>(scores).</span><span>filter</span><span>(x </span><span>-&gt;</span><span><span> x </span><span>&gt;</span><span> avg).</span></span><span>count</span><span>();</span></div></div><div><div><div>34</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"高于平均: "</span><span><span> </span><span>+</span><span> above </span><span>+</span><span> </span></span><span>" 人"</span><span>);</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>2. 矩阵转置<a href="#2-矩阵转置"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Transpose</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>int</span><span><span>[][] </span><span>m</span><span> </span></span><span><span>=</span><span> {{</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>}, {</span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>}};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>        </span><span>int</span><span><span>[][] </span><span>t</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>int</span><span>[m[</span><span>0</span><span>].</span><span>length</span><span>][</span><span>m</span><span>.</span><span>length</span><span>];</span></div></div><div><div><div>6</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>i</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span><span>; i </span><span>&lt;</span><span> </span></span><span>m</span><span>.</span><span>length</span><span>; i++)</span></div></div><div><div><div>7</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>j</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span><span>; j </span><span>&lt;</span><span> m[</span></span><span>0</span><span>].</span><span>length</span><span>; j++)</span></div></div><div><div><div>8</div></div><div><span><span>                </span></span><span>t[j][i] </span><span>=</span><span> m[i][j];</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>Arrays</span><span>.</span><span>deepToString</span><span>(t));</span></div></div><div><div><div>11</div></div><div><span>        </span><span>// [[1, 4], [2, 5], [3, 6]]</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>重载 <code>area</code>：圆（半径）、长方形（宽高）、三角形（三边海伦公式）</li>
<li>写 <code>static void reverse(int[] arr)</code> 原地反转数组（双指针交换，不用新数组）</li>
<li>统计数组中每个元素出现次数（排序后一段一段数；进阶：两重循环去重）</li>
<li>实现 <code>static int[] merge(int[] a, int[] b)</code>：合并两个有序数组为有序数组（归并思想）</li>
<li>模拟”双色球抽奖”：从 1~33 随机取 6 个不重复红球 + 1 个蓝球，Arrays.sort 后输出</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>方法必须住类里；签名 = 名字 + 参数；仅返回值不同不构成重载</li>
<li>Java 只有值传递：传引用改内容有效、改指向无效</li>
<li>可变参数 <code>int...</code> 本质数组，必须放最后</li>
<li>数组定长、length 是属性、越界抛异常</li>
<li>Arrays 工具类五件套：toString / sort / binarySearch / copyOf / equals</li>
<li>二维数组是”数组的数组”，可不规则</li>
</ul><p><strong>下一篇</strong>：面向对象（上）——类、对象、构造方法与封装。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。“值传递本质”的三个实验请务必亲手跑一遍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-05/</id>
      <title type="text">Java 入门教程（五）：面向对象（上）——类与封装</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-05/"/>
      <summary type="text">深入 Java OOP 基础：类与对象、构造方法与方法重载、this 关键字、封装三私有一公开规范、static 与静态成员、包与访问修饰符四档权限，用银行账户与图书系统案例贯穿。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>Java 是纯面向对象语言——<strong>一切代码都在类里</strong>。本篇讲 OOP 第一支柱<strong>封装</strong>：类的设计规范、构造方法、this、static 与包管理。Java 的 OOP 比 C++ 更”强制”也更统一。</p></section>
<section><h2>一、类与对象<a href="#一类与对象"><span>#</span></a></h2><section><h3>第一个正式的类<a href="#第一个正式的类"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Student</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>// 成员变量（字段）—— 对象的属性</span></div></div><div><div><div>3</div></div><div><span>    </span><span>private</span><span> </span><span>String</span><span> name</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>private</span><span> </span><span>int</span><span> age</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>private</span><span> </span><span>double</span><span> score</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>// 构造方法 —— 创建对象的入口</span></div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>Student</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>, </span></span><span>int</span><span><span> </span><span>age</span><span>, </span></span><span>double</span><span><span> </span><span>score</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>this</span><span>.</span><span>name</span><span><span> </span><span>=</span><span> name;          </span></span><span>// this.name 是字段，name 是参数</span></div></div><div><div><div>10</div></div><div><span>        </span><span>this</span><span>.</span><span>age</span><span><span> </span><span>=</span><span> age;</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>this</span><span>.</span><span>score</span><span><span> </span><span>=</span><span> score;</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>// 无参构造（重载）</span></div></div><div><div><div>15</div></div><div><span>    </span><span>public</span><span> </span><span>Student</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>16</div></div><div><span>        </span><span>this</span><span>(</span><span>"未命名"</span><span>, </span><span>0</span><span>, </span><span>0</span><span>);       </span><span>// this(...) 调用另一个构造</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>    </span><span>// getter / setter —— 封装的对外接口</span></div></div><div><div><div>20</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>getName</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> name; }</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>setAge</span><span>(</span><span>int</span><span><span> </span><span>age</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>23</div></div><div><span>        </span><span>if</span><span><span> (age </span><span>&lt;</span><span> </span></span><span>0</span><span><span> </span><span>||</span><span> age </span><span>&gt;</span><span> </span></span><span>150</span><span>) {           </span><span>// setter 里做校验！</span></div></div><div><div><div>24</div></div><div><span>            </span><span>throw</span><span> </span><span>new</span><span> </span><span>IllegalArgumentException</span><span>(</span><span>"年龄非法: "</span><span><span> </span><span>+</span><span> age);</span></span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>        </span><span>this</span><span>.</span><span>age</span><span><span> </span><span>=</span><span> age;</span></span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>getAge</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> age; }</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> </span><span>getScore</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> score; }</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>    </span><span>// 成员方法 —— 对象的行为</span></div></div><div><div><div>33</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>study</span><span>(</span><span>String</span><span><span> </span><span>course</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>34</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>" 正在学习 "</span><span><span> </span><span>+</span><span> course);</span></span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>introduce</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>38</div></div><div><span>        </span><span>return</span><span> </span><span>String</span><span>.</span><span>format</span><span>(</span><span>"我是%s，%d岁，成绩%.1f"</span><span>, name, age, score);</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Main</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>Student</span><span><span> </span><span>ming</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小明"</span><span>, </span><span>18</span><span>, </span><span>90.5</span><span>);   </span><span>// new 创建对象</span></div></div><div><div><div>4</div></div><div><span>        </span><span>Student</span><span><span> </span><span>anon</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Student</span><span>();</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>        </span><span>ming</span><span>.</span><span>study</span><span>(</span><span>"Java"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ming</span><span>.</span><span>introduce</span><span>());</span></div></div><div><div><div>8</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>anon</span><span>.</span><span>introduce</span><span>());</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>ming</span><span>.</span><span>setAge</span><span>(</span><span>19</span><span>);       </span><span>// ✓ 走 setter 校验</span></div></div><div><div><div>11</div></div><div><span>        </span><span>// ming.setAge(-1);    // 抛 IllegalArgumentException —— 封装的价值</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象内存图</strong>（理解关键）：<code>new</code> 在<strong>堆</strong>里开辟对象空间，变量 <code>ming</code> 存的是它的<strong>引用</strong>（地址）；多个变量可引用同一对象。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Student</span><span> a </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小明"</span><span><span>,</span><span> </span></span><span>18</span><span><span>,</span><span> </span></span><span>90</span><span><span>)</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span>Student</span><span> b </span><span><span>=</span><span> a</span><span>;</span><span>               </span></span><span>// b 和 a 指向同一个对象！</span></div></div><div><div><div>3</div></div><div><span>b</span><span>.</span><span>setAge</span><span>(</span><span>20</span><span>);</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>.</span><span>getAge</span><span><span>());</span><span>   </span></span><span>// 20</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> b);</span><span>       </span></span><span>// true（同一地址）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>JavaBean 规范<a href="#javabean-规范"><span>#</span></a></h3><p>字段私有 + 公有 getter/setter + 无参构造——行业通用的数据类写法，IDE 与框架都认这个约定（IDEA 里 <code>Alt+Insert</code> 一键生成）。</p></section></section>
<section><h2>二、this 关键字<a href="#二this-关键字"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Account</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>private</span><span> </span><span>String</span><span> owner</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>private</span><span> </span><span>double</span><span> balance</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>Account</span><span>(</span><span>String</span><span><span> </span><span>owner</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>this</span><span>.</span><span>owner</span><span><span> </span><span>=</span><span> owner;              </span></span><span>// ① 区分字段与同名参数</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>public</span><span> </span><span>Account</span><span>(</span><span>String</span><span><span> </span><span>owner</span><span>, </span></span><span>double</span><span><span> </span><span>balance</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>this</span><span>(owner);                     </span><span>// ② this(...) 调用兄弟构造（必须第一行）</span></div></div><div><div><div>11</div></div><div><span>        </span><span>this</span><span>.</span><span>balance</span><span><span> </span><span>=</span><span> balance;</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>public</span><span> </span><span>Account</span><span> </span><span>deposit</span><span>(</span><span>double</span><span><span> </span><span>amount</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>15</div></div><div><span>        </span><span>if</span><span><span> (amount </span><span>&gt;</span><span> </span></span><span>0</span><span>) </span><span>this</span><span>.</span><span>balance</span><span><span> </span><span>+=</span><span> amount;</span></span></div></div><div><div><div>16</div></div><div><span>        </span><span>return</span><span> </span><span>this</span><span>;                     </span><span>// ③ 返回自身 → 链式调用</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>new</span><span> </span><span>Account</span><span>(</span><span>"小明"</span><span><span>,</span><span> </span></span><span>100</span><span><span>)</span><span>.</span></span><span>deposit</span><span>(</span><span>50</span><span>).</span><span>deposit</span><span>(</span><span>30</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>三、封装三私有一公开<a href="#三封装三私有一公开"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 反例：字段公开</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Bad</span><span> </span></span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> balance</span><span><span>;</span><span>          </span></span><span>// 任何代码都能写 account.balance = -999</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 正例：私有字段 + 校验入口</span></div></div><div><div><div>7</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Good</span><span> </span></span><span>{</span></div></div><div><div><div>8</div></div><div><span>    </span><span>private</span><span> </span><span>double</span><span> balance</span><span><span>;</span><span>         </span></span><span>// 外部不可见</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>deposit</span><span>(</span><span>double</span><span><span> </span><span>amount</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span><span> (amount </span><span>&lt;=</span><span> </span></span><span>0</span><span>) </span><span>throw</span><span> </span><span>new</span><span> </span><span>IllegalArgumentException</span><span>(</span><span>"金额必须为正"</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>balance </span><span>+=</span><span> amount;          </span><span>// 修改必经校验</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> </span><span>getBalance</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> balance; }</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>封装心法</strong>：字段全部 private，外界只通过方法访问——<strong>所有修改必须经过你的检查</strong>，不变量（余额非负）由类自己守护。</p></section>
<section><h2>四、static：属于类的成员<a href="#四static属于类的成员"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>GameCharacter</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>// 静态字段：全类共享一份（不属于任何对象）</span></div></div><div><div><div>3</div></div><div><span>    </span><span>private</span><span> </span><span>static</span><span> </span><span>int</span><span> createdCount </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>static</span><span> </span><span>final</span><span> </span><span>int</span><span> MAX_LEVEL </span><span><span>=</span><span> </span></span><span>99</span><span><span>;</span><span>          </span></span><span>// 静态常量</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>// 实例字段：每个对象一份</span></div></div><div><div><div>7</div></div><div><span>    </span><span>private</span><span> </span><span>String</span><span> name</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>private</span><span> </span><span>int</span><span> level</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>public</span><span> </span><span>GameCharacter</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>this</span><span>.</span><span>name</span><span><span> </span><span>=</span><span> name;</span></span></div></div><div><div><div>12</div></div><div><span>        </span><span>this</span><span>.</span><span>level</span><span><span> </span><span>=</span><span> </span></span><span>1</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>createdCount++;                        </span><span>// 每创建一个 +1</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>// 静态方法：属于类，没有 this（不能访问实例成员！）</span></div></div><div><div><div>17</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>int</span><span> </span><span>getCreatedCount</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>18</div></div><div><span>        </span><span>// System.out.println(this.name);     // ❌ 编译错误，静态无 this</span></div></div><div><div><div>19</div></div><div><span>        </span><span>return</span><span> createdCount;</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>23</div></div><div><span>        </span><span>new</span><span> </span><span>GameCharacter</span><span>(</span><span>"勇者"</span><span>);</span></div></div><div><div><div>24</div></div><div><span>        </span><span>new</span><span> </span><span>GameCharacter</span><span>(</span><span>"法师"</span><span>);</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>GameCharacter</span><span>.</span><span>getCreatedCount</span><span>());   </span><span>// 2（用类名调）</span></div></div><div><div><div>27</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>GameCharacter</span><span>.</span><span>MAX_LEVEL</span><span>);</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>静态 vs 实例决策</strong>：跟着<strong>对象</strong>走的（名字、等级）→ 实例成员；<strong>全类共享/统计/常量/工具方法</strong> → 静态成员。</p><p><strong>main 为什么是 static</strong>：程序启动时还没有任何对象，JVM 只能用类名调起入口。</p></section>
<section><h2>五、包与访问权限<a href="#五包与访问权限"><span>#</span></a></h2><section><h3>包（package）：类的目录组织<a href="#包package类的目录组织"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 文件 src/com/club/utils/MathUtils.java</span></div></div><div><div><div>2</div></div><div><span>package</span><span><span> </span><span>com.club.utils</span><span>;</span><span>                    </span></span><span>// 第一行声明包（对应目录结构）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>MathUtils</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>boolean</span><span> </span><span>isPrime</span><span>(</span><span>int</span><span><span> </span><span>n</span><span>)</span><span> </span><span>{ </span></span><span>/* ... */</span><span> </span><span>return</span><span> </span><span>true</span><span>; }</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 使用方</span></div></div><div><div><div>9</div></div><div><span>import</span><span> </span><span>com.club.utils.MathUtils</span><span><span>;</span><span>           </span></span><span>// 导入</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Main</span><span> </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>MathUtils</span><span>.</span><span>isPrime</span><span>(</span><span>7</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>IDEA 建 <code>com.club.utils</code> 包，把类放进去即可自动管理。</p></section><section><h3>四档访问权限<a href="#四档访问权限"><span>#</span></a></h3>

<table><thead><tr><th>修饰符</th><th>本类</th><th>同包</th><th>子类</th><th>其他包</th></tr></thead><tbody><tr><td><code>private</code></td><td>✓</td><td></td><td></td><td></td></tr><tr><td>（默认，不写）</td><td>✓</td><td>✓</td><td></td><td></td></tr><tr><td><code>protected</code></td><td>✓</td><td>✓</td><td>✓</td><td></td></tr><tr><td><code>public</code></td><td>✓</td><td>✓</td><td>✓</td><td>✓</td></tr></tbody></table><p><strong>实用建议</strong>：字段 private；方法按需要 public；仅供包内协作的用默认/protected。</p></section></section>
<section><h2>六、综合案例：图书借阅系统（封装版）<a href="#六综合案例图书借阅系统封装版"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.ArrayList</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Library</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>// ===== 内部数据类 =====</span></div></div><div><div><div>6</div></div><div><span>    </span><span>private</span><span> </span><span>static</span><span> </span><span>class</span><span><span> </span><span>Book</span><span> </span></span><span>{</span></div></div><div><div><div>7</div></div><div><span>        </span><span>private</span><span> </span><span>final</span><span> </span><span>String</span><span> isbn</span><span>;</span></div></div><div><div><div>8</div></div><div><span>        </span><span>private</span><span> </span><span>final</span><span> </span><span>String</span><span> title</span><span>;</span></div></div><div><div><div>9</div></div><div><span>        </span><span>private</span><span> </span><span>boolean</span><span> borrowed</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>Book</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>, </span></span><span>String</span><span><span> </span><span>title</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>12</div></div><div><span>            </span><span>this</span><span>.</span><span>isbn</span><span><span> </span><span>=</span><span> isbn;</span></span></div></div><div><div><div>13</div></div><div><span>            </span><span>this</span><span>.</span><span>title</span><span><span> </span><span>=</span><span> title;</span></span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>        </span><span>String</span><span> </span><span>getTitle</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> title; }</span></div></div><div><div><div>16</div></div><div><span>        </span><span>String</span><span> </span><span>getIsbn</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> isbn; }</span></div></div><div><div><div>17</div></div><div><span>        </span><span>boolean</span><span> </span><span>isBorrowed</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> borrowed; }</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>    </span><span>// ===== 业务异常 =====</span></div></div><div><div><div>21</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>class</span><span><span> </span><span>LibraryException</span><span> </span></span><span>extends</span><span><span> </span><span>RuntimeException</span><span> </span></span><span>{</span></div></div><div><div><div>22</div></div><div><span>        </span><span>LibraryException</span><span>(</span><span>String</span><span><span> </span><span>msg</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(msg); }</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>    </span><span>// ===== 状态封装在 Library 内 =====</span></div></div><div><div><div>26</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>List</span><span>&lt;</span><span>Book</span><span><span>&gt;</span><span> books </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>addBook</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>, </span></span><span>String</span><span><span> </span><span>title</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>29</div></div><div><span>        </span><span>if</span><span> (</span><span>findBook</span><span><span>(isbn) </span><span>!=</span><span> </span></span><span>null</span><span>)</span></div></div><div><div><div>30</div></div><div><span>            </span><span>throw</span><span> </span><span>new</span><span> </span><span>LibraryException</span><span>(</span><span>"ISBN 已存在: "</span><span><span> </span><span>+</span><span> isbn);</span></span></div></div><div><div><div>31</div></div><div><span>        </span><span>books</span><span>.</span><span>add</span><span>(</span><span>new</span><span> </span><span>Book</span><span>(isbn, title));</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>borrow</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>35</div></div><div><span>        </span><span>Book</span><span><span> </span><span>b</span><span> </span></span><span><span>=</span><span> </span></span><span>requireBook</span><span>(isbn);</span></div></div><div><div><div>36</div></div><div><span>        </span><span>if</span><span> (</span><span>b</span><span>.</span><span>borrowed</span><span>)</span></div></div><div><div><div>37</div></div><div><span>            </span><span>throw</span><span> </span><span>new</span><span> </span><span>LibraryException</span><span>(</span><span>"《"</span><span><span> </span><span>+</span><span> </span></span><span>b</span><span>.</span><span>getTitle</span><span><span>() </span><span>+</span><span> </span></span><span>"》已借出"</span><span>);</span></div></div><div><div><div>38</div></div><div><span>        </span><span>b</span><span>.</span><span>borrowed</span><span><span> </span><span>=</span><span> </span></span><span>true</span><span>;</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>giveBack</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>42</div></div><div><span>        </span><span>requireBook</span><span>(isbn).</span><span>borrowed</span><span><span> </span><span>=</span><span> </span></span><span>false</span><span>;</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>listAll</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>46</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"—— 馆藏 "</span><span><span> </span><span>+</span><span> </span></span><span>books</span><span>.</span><span>size</span><span><span>() </span><span>+</span><span> </span></span><span>" 本 ——"</span><span>);</span></div></div><div><div><div>47</div></div><div><span>        </span><span>for</span><span> (</span><span>Book</span><span><span> </span><span>b</span><span> </span></span><span>:</span><span> books)</span></div></div><div><div><div>48</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%-14s %-20s %s%n"</span><span>,</span></div></div><div><div><div>49</div></div><div><span>                    </span><span>b</span><span>.</span><span>getIsbn</span><span>(), </span><span>b</span><span>.</span><span>getTitle</span><span>(),</span></div></div><div><div><div>50</div></div><div><span>                    </span><span>b</span><span>.</span><span>isBorrowed</span><span>() </span><span>?</span><span> </span><span>"[借出]"</span><span> </span><span>:</span><span> </span><span>"[在架]"</span><span>);</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>    </span><span>private</span><span> </span><span>Book</span><span> </span><span>findBook</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>)</span><span> </span><span>{          </span></span><span>// 私有工具方法</span></div></div><div><div><div>54</div></div><div><span>        </span><span>for</span><span> (</span><span>Book</span><span><span> </span><span>b</span><span> </span></span><span>:</span><span> books)</span></div></div><div><div><div>55</div></div><div><span>            </span><span>if</span><span> (</span><span>b</span><span>.</span><span>getIsbn</span><span>().</span><span>equals</span><span>(isbn)) </span><span>return</span><span> b;</span></div></div><div><div><div>56</div></div><div><span>        </span><span>return</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>57</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>58</div></div><div>
</div></div><div><div><div>59</div></div><div><span>    </span><span>private</span><span> </span><span>Book</span><span> </span><span>requireBook</span><span>(</span><span>String</span><span><span> </span><span>isbn</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>60</div></div><div><span>        </span><span>Book</span><span><span> </span><span>b</span><span> </span></span><span><span>=</span><span> </span></span><span>findBook</span><span>(isbn);</span></div></div><div><div><div>61</div></div><div><span>        </span><span>if</span><span><span> (b </span><span>==</span><span> </span></span><span>null</span><span>) </span><span>throw</span><span> </span><span>new</span><span> </span><span>LibraryException</span><span>(</span><span>"无此书: "</span><span><span> </span><span>+</span><span> isbn);</span></span></div></div><div><div><div>62</div></div><div><span>        </span><span>return</span><span> b;</span></div></div><div><div><div>63</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>66</div></div><div><span>        </span><span>Library</span><span><span> </span><span>lib</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Library</span><span>();</span></div></div><div><div><div>67</div></div><div><span>        </span><span>lib</span><span>.</span><span>addBook</span><span>(</span><span>"978-7-111"</span><span>, </span><span>"Java 核心技术"</span><span>);</span></div></div><div><div><div>68</div></div><div><span>        </span><span>lib</span><span>.</span><span>addBook</span><span>(</span><span>"978-7-115"</span><span>, </span><span>"算法（第4版）"</span><span>);</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span>        </span><span>lib</span><span>.</span><span>borrow</span><span>(</span><span>"978-7-111"</span><span>);</span></div></div><div><div><div>71</div></div><div><span>        </span><span>lib</span><span>.</span><span>listAll</span><span>();</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>74</div></div><div><span>            </span><span>lib</span><span>.</span><span>borrow</span><span>(</span><span>"978-7-111"</span><span>);          </span><span>// 重复借</span></div></div><div><div><div>75</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>LibraryException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>76</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"❌ "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>77</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>78</div></div><div><span>        </span><span>lib</span><span>.</span><span>giveBack</span><span>(</span><span>"978-7-111"</span><span>);</span></div></div><div><div><div>79</div></div><div><span>        </span><span>lib</span><span>.</span><span>listAll</span><span>();</span></div></div><div><div><div>80</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>81</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>设计观察</strong>：Book 是 private static 内部类（外界无需知道它的存在）、books 私有（只能通过借/还改变状态）、所有业务错误抛统一异常——这就是封装的完整形态。ArrayList 细节下下篇讲。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>实现 <code>Rectangle</code> JavaBean：私有宽高 + getter/setter（负数抛异常）+ <code>area()</code>/<code>perimeter()</code></li>
<li>写 <code>Counter</code> 类：静态字段统计创建的对象数、实例方法 <code>id()</code> 返回自己的序号</li>
<li>银行账户 <code>BankAccount</code>：私有余额，<code>deposit</code>/<code>withdraw</code>（不足抛异常）、静态方法统计总账户数与总存款</li>
<li>建 <code>com.club.shape</code> 包放 Shape 类、<code>com.club.main</code> 包写 Main 调用（练习 package/import）</li>
<li>给 Student 加 <code>compareTo</code> 风格方法 <code>betterThan(Student other)</code> 按成绩比较，main 里造 3 个对象找学霸</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>字段私有 + getter/setter + 无参构造 = JavaBean 规范</li>
<li>this 三用：区名字 / this(…) 链构造 / 返回自身链式调用</li>
<li>引用变量存地址；<code>==</code> 比地址、内容比较用 equals（第七篇详讲）</li>
<li>static 属于类；静态方法无 this 不能摸实例成员</li>
<li>四档权限：private → 默认 → protected → public</li>
<li>封装的本质：状态私有，修改必经校验</li>
</ul><p><strong>下一篇</strong>：面向对象（下）——继承、多态、接口与抽象类，Java OOP 的完全体。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。IDEA 的 Alt+Insert（生成 getter/setter/构造）先练熟，生产力 ×10。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-06/</id>
      <title type="text">Java 入门教程（六）：面向对象（下）——继承、多态与接口</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-06/"/>
      <summary type="text">讲透 Java OOP 完全体：继承与 super、方法重写规则、多态与动态绑定、抽象类、接口（默认/静态方法）、Object 核心方法（equals/hashCode/toString）、final 三用法与组合原则。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>OOP 剩余两大支柱<strong>继承与多态</strong>，以及 Java 的招牌——<strong>接口</strong>。Spring 等主流框架的根基全在本篇。学完后你能读懂 JDK 源码结构和绝大多数 Java 项目的类设计。</p></section>
<section><h2>一、继承<a href="#一继承"><span>#</span></a></h2><section><h3>extends 与 super<a href="#extends-与-super"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 父类</span></div></div><div><div><div>2</div></div><div><span>class</span><span><span> </span><span>Animal</span><span> </span></span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>protected</span><span> </span><span>String</span><span> name</span><span><span>;</span><span>          </span></span><span>// protected：子类可用</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>Animal</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>this</span><span>.</span><span>name</span><span><span> </span><span>=</span><span> name;</span></span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>eat</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>" 在吃东西"</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 子类：Java 单继承（一个类只能 extends 一个父类）</span></div></div><div><div><div>15</div></div><div><span>class</span><span><span> </span><span>Dog</span><span> </span></span><span>extends</span><span><span> </span><span>Animal</span><span> </span></span><span>{</span></div></div><div><div><div>16</div></div><div><span>    </span><span>private</span><span> </span><span>String</span><span> breed</span><span>;</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>public</span><span> </span><span>Dog</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>, </span></span><span>String</span><span><span> </span><span>breed</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>19</div></div><div><span>        </span><span>super</span><span>(name);                </span><span>// ⚠ 必须第一行：调用父类构造</span></div></div><div><div><div>20</div></div><div><span>        </span><span>this</span><span>.</span><span>breed</span><span><span> </span><span>=</span><span> breed;</span></span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>fetch</span><span><span>()</span><span> </span><span>{           </span></span><span>// 子类新增方法</span></div></div><div><div><div>24</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>" 去捡球"</span><span>);</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>Dog</span><span> d </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span><span>,</span><span> </span></span><span>"柴犬"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>29</div></div><div><span>d</span><span>.</span><span>eat</span><span><span>();</span><span>        </span></span><span>// 继承的</span></div></div><div><div><div>30</div></div><div><span>d</span><span>.</span><span>fetch</span><span><span>();</span><span>      </span></span><span>// 自己的</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>构造顺序</strong>：父类构造先执行（super）→ 子类构造。不写 super(…) 时编译器默认补 <code>super()</code>（父类必须有无参构造，否则报错）。</p></section><section><h3>方法重写（Override）<a href="#方法重写override"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Cat</span><span> </span></span><span>extends</span><span><span> </span><span>Animal</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>Cat</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(name); }</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>@</span><span>Override</span><span>                          </span><span>// 注解：让编译器检查重写合法性</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>eat</span><span><span>()</span><span> </span><span>{                </span></span><span>// 方法签名与父类完全一致</span></div></div><div><div><div>6</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(name </span><span>+</span><span> </span></span><span>"：吃小鱼干"</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>重写规则（两同两小一大）</strong>：</p><ul>
<li>方法名、参数列表<strong>相同</strong></li>
<li>返回值<strong>小于等于</strong>父类（相同或是子类型）</li>
<li>异常<strong>小于等于</strong>父类抛的</li>
<li>访问权限<strong>大于等于</strong>父类（父 public 子不能 protected）</li>
</ul><p><strong>@Override 必写</strong>——拼写错误、签名不匹配时编译器立刻报错。</p></section></section>
<section><h2>二、多态<a href="#二多态"><span>#</span></a></h2><section><h3>向上转型与动态绑定<a href="#向上转型与动态绑定"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Animal</span><span> a1 </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span><span>,</span><span> </span></span><span>"柴犬"</span><span><span>)</span><span>;</span><span>    </span></span><span>// 向上转型：子对象当父类型用</span></div></div><div><div><div>2</div></div><div><span>Animal</span><span> a2 </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Cat</span><span>(</span><span>"咪咪"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>a1</span><span>.</span><span>eat</span><span><span>();</span><span>      </span></span><span>// ？——调用谁的 eat？</span></div></div><div><div><div>5</div></div><div><span>a2</span><span>.</span><span>eat</span><span>();</span></div></div><div><div><div>6</div></div><div><span>// 输出：旺财 在吃东西 / 咪咪：吃小鱼干</span></div></div><div><div><div>7</div></div><div><span>// dog 覆写了 eat → 运行期按真实对象类型绑定！</span></div></div><div><div><div>8</div></div><div><span>// a1.fetch();  ❌ 编译错误：Animal 类型看不见 Dog 特有方法</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>多态三条件</strong>：继承体系 + 方法重写 + 父类引用指向子类对象。</p><p><strong>编译看左、运行看右</strong>：能调什么方法由<strong>引用类型</strong>（左边）决定，实际执行哪个版本由<strong>对象类型</strong>（右边）决定。</p></section><section><h3>多态的威力：统一处理<a href="#多态的威力统一处理"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Zoo</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>feedAll</span><span>(</span><span>Animal</span><span><span>[] </span><span>animals</span><span>)</span><span> </span><span>{   </span></span><span>// 一个方法管所有动物</span></div></div><div><div><div>3</div></div><div><span>        </span><span>for</span><span> (</span><span>Animal</span><span><span> </span><span>a</span><span> </span></span><span>:</span><span> animals) {</span></div></div><div><div><div>4</div></div><div><span>            </span><span>a</span><span>.</span><span>eat</span><span>();                                  </span><span>// 各自动态绑定</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>feedAll</span><span>(</span><span>new</span><span> </span><span>Animal</span><span>[]{</span></div></div><div><div><div>10</div></div><div><span>            </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span>, </span><span>"柴犬"</span><span>),</span></div></div><div><div><div>11</div></div><div><span>            </span><span>new</span><span> </span><span>Cat</span><span>(</span><span>"咪咪"</span><span>),</span></div></div><div><div><div>12</div></div><div><span>            </span><span>new</span><span> </span><span>Animal</span><span>(</span><span>"神秘生物"</span><span>),</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>新增 <code>Bird</code> 子类？<code>feedAll</code> 一行不改——<strong>开闭原则</strong>。</p></section><section><h3>向下转型与 instanceof<a href="#向下转型与-instanceof"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Animal</span><span> a </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Dog</span><span>(</span><span>"旺财"</span><span><span>,</span><span> </span></span><span>"柴犬"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span> (a </span><span>instanceof</span><span> Dog) {              </span><span>// 先判断再转（否则 ClassCastException）</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Dog</span><span> d </span><span><span>=</span><span> (Dog) a</span><span>;</span><span>                 </span></span><span>// 向下转型：恢复子类能力</span></div></div><div><div><div>5</div></div><div><span>    </span><span>d</span><span>.</span><span>fetch</span><span>();</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// Java 16+ 模式匹配（一步到位）</span></div></div><div><div><div>9</div></div><div><span>if</span><span> (a </span><span>instanceof</span><span> </span><span>Dog</span><span> d) {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>d</span><span>.</span><span>fetch</span><span><span>();</span><span>                       </span></span><span>// d 已就绪</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、抽象类<a href="#三抽象类"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>abstract</span><span> </span><span>class</span><span><span> </span><span>Shape</span><span> </span></span><span><span>{</span><span>                      </span></span><span>// abstract 类不能 new</span></div></div><div><div><div>2</div></div><div><span>    </span><span>protected</span><span> </span><span>String</span><span> name</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>protected</span><span> </span><span>Shape</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>name</span><span><span> </span><span>=</span><span> name; }</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>public</span><span> </span><span>abstract</span><span> </span><span>double</span><span> </span><span>area</span><span><span>();</span><span>          </span></span><span>// 抽象方法：无实现，子类必须实现</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>describe</span><span><span>()</span><span> </span><span>{                </span></span><span>// 普通方法：可复用</span></div></div><div><div><div>9</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%s 的面积 = %.2f%n"</span><span>, name, </span><span>area</span><span>());   </span><span>// 多态调用</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>class</span><span><span> </span><span>Circle</span><span> </span></span><span>extends</span><span><span> </span><span>Shape</span><span> </span></span><span>{</span></div></div><div><div><div>14</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>double</span><span> r</span><span>;</span></div></div><div><div><div>15</div></div><div><span>    </span><span>public</span><span> </span><span>Circle</span><span>(</span><span>double</span><span><span> </span><span>r</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(</span><span>"圆"</span><span>); </span><span>this</span><span>.</span><span>r</span><span><span> </span><span>=</span><span> r; }</span></span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>18</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> </span><span>area</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>Math</span><span>.</span><span>PI</span><span><span> </span><span>*</span><span> r </span><span>*</span><span> r; }</span></span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>class</span><span><span> </span><span>Rect</span><span> </span></span><span>extends</span><span><span> </span><span>Shape</span><span> </span></span><span>{</span></div></div><div><div><div>22</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>double</span><span><span> w</span><span>,</span><span> h</span></span><span>;</span></div></div><div><div><div>23</div></div><div><span>    </span><span>public</span><span> </span><span>Rect</span><span>(</span><span>double</span><span><span> </span><span>w</span><span>, </span></span><span>double</span><span><span> </span><span>h</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(</span><span>"矩形"</span><span>); </span><span>this</span><span>.</span><span>w</span><span><span> </span><span>=</span><span> w; </span></span><span>this</span><span>.</span><span>h</span><span><span> </span><span>=</span><span> h; }</span></span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>26</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> </span><span>area</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span><span> w </span><span>*</span><span> h; }</span></span></div></div><div><div><div>27</div></div><div><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>// Shape s = new Shape("x");   ❌ 抽象类不能实例化</span></div></div><div><div><div>30</div></div><div><span>Shape</span><span> s </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Circle</span><span>(</span><span>2</span><span><span>)</span><span>;</span></span></div></div><div><div><div>31</div></div><div><span>s</span><span>.</span><span>describe</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>抽象类定位</strong>：模板/半成品——提取公共部分（字段、实现），强制子类完成”填空”（抽象方法）。</p></section>
<section><h2>四、接口（Java 的招牌）<a href="#四接口java-的招牌"><span>#</span></a></h2><section><h3>定义与实现<a href="#定义与实现"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 接口：纯契约（方法默认 public abstract）</span></div></div><div><div><div>2</div></div><div><span>interface</span><span><span> </span><span>Comparable2</span><span>&lt;</span><span>T</span><span>&gt;</span><span> </span></span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> </span><span>compareTo</span><span>(</span><span>T</span><span><span> </span><span>other</span><span>);</span><span>                 </span></span><span>// 抽象方法</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>interface</span><span><span> </span><span>Swimmer</span><span> </span></span><span>{</span></div></div><div><div><div>7</div></div><div><span>    </span><span>void</span><span> </span><span>swim</span><span>();</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>// Java 8+ 允许默认方法（有实现！）</span></div></div><div><div><div>10</div></div><div><span>    </span><span>default</span><span> </span><span>void</span><span> </span><span>swimFast</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"加速游动"</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>// Java 8+ 静态方法</span></div></div><div><div><div>15</div></div><div><span>    </span><span>static</span><span> </span><span>void</span><span> </span><span>info</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>16</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"游泳接口 v1.0"</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>interface</span><span><span> </span><span>Walker</span><span> </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>    </span><span>void</span><span> </span><span>walk</span><span>();</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>// 类可实现多个接口（多继承能力的替代品！）</span></div></div><div><div><div>25</div></div><div><span>class</span><span><span> </span><span>Duck</span><span> </span></span><span>implements</span><span><span> </span><span>Swimmer</span><span>,</span><span> </span><span>Walker</span><span> </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>27</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>swim</span><span><span>()</span><span> </span><span>{ </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"鸭子划水"</span><span>); }</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>29</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>walk</span><span><span>()</span><span> </span><span>{ </span></span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"鸭子摇摆走"</span><span>); }</span></div></div><div><div><div>30</div></div><div><span>}</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>Duck</span><span> d </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Duck</span><span><span>()</span><span>;</span></span></div></div><div><div><div>33</div></div><div><span>d</span><span>.</span><span>swim</span><span><span>();</span><span> </span></span><span>d</span><span>.</span><span>walk</span><span><span>();</span><span> </span></span><span>d</span><span>.</span><span>swimFast</span><span><span>();</span><span>          </span></span><span>// 默认方法直接用</span></div></div><div><div><div>34</div></div><div><span>Swimmer</span><span>.</span><span>info</span><span><span>();</span><span>                             </span></span><span>// 静态方法接口名调</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>接口 vs 抽象类<a href="#接口-vs-抽象类"><span>#</span></a></h3>

<table><thead><tr><th>维度</th><th>抽象类</th><th>接口</th></tr></thead><tbody><tr><td>关键词</td><td><code>extends</code> 单继承</td><td><code>implements</code> 多实现</td></tr><tr><td>字段</td><td>任意</td><td>只能 <code>public static final</code> 常量</td></tr><tr><td>构造方法</td><td>有</td><td>无</td></tr><tr><td>方法</td><td>抽象+具体</td><td>抽象+default+static</td></tr><tr><td>语义</td><td>“是什么”（is-a，模板）</td><td>“能做什么”（can-do，能力）</td></tr></tbody></table><p><strong>经验</strong>：定义”身份与模板”用抽象类（Animal）；定义”能力”用接口（Comparable、Runnable、Swimmer）——类可以同时是动物并能游泳能跑。</p></section><section><h3>面向接口编程（框架思维）<a href="#面向接口编程框架思维"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>interface</span><span><span> </span><span>Storage</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>void</span><span> </span><span>save</span><span>(</span><span>String</span><span><span> </span><span>key</span><span>, </span></span><span>String</span><span><span> </span><span>value</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>String</span><span> </span><span>load</span><span>(</span><span>String</span><span><span> </span><span>key</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>class</span><span><span> </span><span>MemoryStorage</span><span> </span></span><span>implements</span><span><span> </span><span>Storage</span><span> </span></span><span>{</span></div></div><div><div><div>7</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>java</span><span>.</span><span>util</span><span>.</span><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>String</span><span><span>&gt;</span><span> data </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>java</span><span>.</span><span>util</span><span>.</span><span>HashMap</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>save</span><span>(</span><span>String</span><span><span> </span><span>k</span><span>, </span></span><span>String</span><span><span> </span><span>v</span><span>)</span><span> </span><span>{ </span></span><span>data</span><span>.</span><span>put</span><span>(k, v); }</span></div></div><div><div><div>9</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>load</span><span>(</span><span>String</span><span><span> </span><span>k</span><span>)</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>data</span><span>.</span><span>get</span><span>(k); }</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>class</span><span><span> </span><span>FileStorage</span><span> </span></span><span>implements</span><span><span> </span><span>Storage</span><span> </span></span><span><span>{</span><span>          </span></span><span>// 换个实现...</span></div></div><div><div><div>13</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>save</span><span>(</span><span>String</span><span><span> </span><span>k</span><span>, </span></span><span>String</span><span><span> </span><span>v</span><span>)</span><span> </span><span>{ </span></span><span>/* 写文件 */</span><span> }</span></div></div><div><div><div>14</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>load</span><span>(</span><span>String</span><span><span> </span><span>k</span><span>)</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>null</span><span>; }</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>// 使用方只依赖接口——实现随换随用（这就是"解耦"）</span></div></div><div><div><div>18</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>App</span><span> </span></span><span>{</span></div></div><div><div><div>19</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>Storage</span><span> storage</span><span><span>;</span><span>               </span></span><span>// 面向接口</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>public</span><span> </span><span>App</span><span>(</span><span>Storage</span><span><span> </span><span>storage</span><span>)</span><span> </span><span>{                </span></span><span>// 构造注入（Spring 核心思想雏形）</span></div></div><div><div><div>22</div></div><div><span>        </span><span>this</span><span>.</span><span>storage</span><span><span> </span><span>=</span><span> storage;</span></span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>run</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>26</div></div><div><span>        </span><span>storage</span><span>.</span><span>save</span><span>(</span><span>"token"</span><span>, </span><span>"abc123"</span><span>);</span></div></div><div><div><div>27</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>storage</span><span>.</span><span>load</span><span>(</span><span>"token"</span><span>));</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>31</div></div><div><span>        </span><span>new</span><span> </span><span>App</span><span>(</span><span>new</span><span> </span><span>MemoryStorage</span><span>()).</span><span>run</span><span>();      </span><span>// 内存版</span></div></div><div><div><div>32</div></div><div><span>        </span><span>new</span><span> </span><span>App</span><span>(</span><span>new</span><span> </span><span>FileStorage</span><span>()).</span><span>run</span><span>();        </span><span>// 文件版——App 一行不改</span></div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>五、Object 三巨头<a href="#五object-三巨头"><span>#</span></a></h2><p>所有类隐式继承 <code>Object</code>，三个方法必须会改写：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Money</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>long</span><span> cents</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>Money</span><span>(</span><span>long</span><span><span> </span><span>cents</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>cents</span><span><span> </span><span>=</span><span> cents; }</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>// 1. equals：内容比较（== 才是引用比较）</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>boolean</span><span> </span><span>equals</span><span>(</span><span>Object</span><span><span> </span><span>o</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>if</span><span> (</span><span>this</span><span><span> </span><span>==</span><span> o) </span></span><span>return</span><span> </span><span>true</span><span>;                       </span><span>// 同一对象</span></div></div><div><div><div>10</div></div><div><span>        </span><span>if</span><span><span> (</span><span>!</span><span>(o </span></span><span>instanceof</span><span> Money)) </span><span>return</span><span> </span><span>false</span><span>;          </span><span>// 类型检查</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span><span> cents </span><span>==</span><span> ((Money) o).</span></span><span>cents</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>// 2. hashCode：equals 相等 → hashCode 必须相等（HashMap 约定）</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>16</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>hashCode</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>Long</span><span>.</span><span>hashCode</span><span>(cents); }</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>// 3. toString：打印友好</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>20</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>toString</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>"¥"</span><span><span> </span><span>+</span><span> cents </span><span>/</span><span> </span></span><span>100.0</span><span>; }</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>Money</span><span> a </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Money</span><span>(</span><span>1050</span><span><span>)</span><span>,</span><span> b </span><span>=</span><span> </span></span><span>new</span><span> </span><span>Money</span><span>(</span><span>1050</span><span><span>)</span><span>;</span></span></div></div><div><div><div>24</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>.</span><span>equals</span><span><span>(b));</span><span>    </span></span><span>// true</span></div></div><div><div><div>25</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a);</span><span>              </span></span><span>// ¥10.5</span></div></div><div><div><div>26</div></div><div><span>// IDEA：Alt+Insert 一键生成三者，日常用工具生成</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div></div><div>Warning</div></div><div><p>只重写 equals 不重写 hashCode 是大坑——HashMap/HashSet 会”找不到”相等的对象。永远两个一起改。</p></div></div></section>
<section><h2>六、final 与继承的边界<a href="#六final-与继承的边界"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>final</span><span> </span><span>class</span><span><span> </span><span>Sealed</span><span> </span></span><span><span>{</span><span> </span><span>}</span><span>              </span></span><span>// final 类：禁止继承（如 String）</span></div></div><div><div><div>2</div></div><div><span>// class Sub extends Sealed {}      ❌</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>class</span><span><span> </span><span>Tool</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>final</span><span> </span><span>void</span><span> </span><span>spec</span><span><span>()</span><span> </span><span>{ }</span><span>    </span></span><span>// final 方法：禁止重写</span></div></div><div><div><div>6</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>final</span><span> </span><span>int</span><span><span> </span><span>X</span><span> </span></span><span><span>=</span><span> </span></span><span>10</span><span>;           </span><span>// final 变量：常量</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>七、综合实战：图形面积系统（接口版）<a href="#七综合实战图形面积系统接口版"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>interface</span><span><span> </span><span>Area</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>double</span><span> </span><span>area</span><span>();</span></div></div><div><div><div>5</div></div><div><span>    </span><span>// 接口 default 提供组合逻辑</span></div></div><div><div><div>6</div></div><div><span>    </span><span>default</span><span> </span><span>double</span><span> </span><span>areaDifference</span><span>(</span><span>Area</span><span><span> </span><span>other</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>return</span><span> </span><span>this</span><span>.</span><span>area</span><span><span>() </span><span>-</span><span> </span></span><span>other</span><span>.</span><span>area</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>class</span><span><span> </span><span>Circle2</span><span> </span></span><span>implements</span><span><span> </span><span>Area</span><span> </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>double</span><span> r</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>Circle2</span><span>(</span><span>double</span><span><span> </span><span>r</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>r</span><span><span> </span><span>=</span><span> r; }</span></span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>@</span><span>Override</span><span> </span><span>public</span><span> </span><span>double</span><span> </span><span>area</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>Math</span><span>.</span><span>PI</span><span><span> </span><span>*</span><span> r </span><span>*</span><span> r; }</span></span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>@</span><span>Override</span><span> </span><span>public</span><span> </span><span>String</span><span> </span><span>toString</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>String</span><span>.</span><span>format</span><span>(</span><span>"圆(r=%.1f)"</span><span>, r); }</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>class</span><span><span> </span><span>Square</span><span> </span></span><span>implements</span><span><span> </span><span>Area</span><span> </span></span><span>{</span></div></div><div><div><div>19</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>double</span><span> side</span><span>;</span></div></div><div><div><div>20</div></div><div><span>    </span><span>Square</span><span>(</span><span>double</span><span><span> </span><span>side</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>side</span><span><span> </span><span>=</span><span> side; }</span></span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>@</span><span>Override</span><span> </span><span>public</span><span> </span><span>double</span><span> </span><span>area</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span><span> side </span><span>*</span><span> side; }</span></span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>@</span><span>Override</span><span> </span><span>public</span><span> </span><span>String</span><span> </span><span>toString</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>String</span><span>.</span><span>format</span><span>(</span><span>"正方形(边%.1f)"</span><span>, side); }</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Shapes</span><span> </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>27</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>Area</span><span><span>&gt; </span><span>shapes</span><span> </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>new</span><span> </span><span>Circle2</span><span>(</span><span>2</span><span>), </span><span>new</span><span> </span><span>Square</span><span>(</span><span>3</span><span>));</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>        </span><span>double</span><span><span> </span><span>total</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>30</div></div><div><span>        </span><span>Area</span><span><span> </span><span>biggest</span><span> </span></span><span><span>=</span><span> </span></span><span>shapes</span><span>.</span><span>get</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>31</div></div><div><span>        </span><span>for</span><span> (</span><span>Area</span><span><span> </span><span>s</span><span> </span></span><span>:</span><span> shapes) {</span></div></div><div><div><div>32</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%s = %.2f%n"</span><span>, s, </span><span>s</span><span>.</span><span>area</span><span>());</span></div></div><div><div><div>33</div></div><div><span><span>            </span></span><span>total </span><span>+=</span><span> </span><span>s</span><span>.</span><span>area</span><span>();</span></div></div><div><div><div>34</div></div><div><span>            </span><span>if</span><span> (</span><span>s</span><span>.</span><span>area</span><span><span>() </span><span>&gt;</span><span> </span></span><span>biggest</span><span>.</span><span>area</span><span><span>()) biggest </span><span>=</span><span> s;</span></span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"总面积 %.2f，最大的是 %s%n"</span><span>, total, biggest);</span></div></div><div><div><div>37</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"圆比正方形大 %.2f%n"</span><span>,</span></div></div><div><div><div>38</div></div><div><span>                </span><span>shapes</span><span>.</span><span>get</span><span>(</span><span>0</span><span>).</span><span>areaDifference</span><span>(</span><span>shapes</span><span>.</span><span>get</span><span>(</span><span>1</span><span>)));</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li><code>Employee</code> 抽象类 + <code>Manager</code>（底薪+提成）/<code>Sales</code>（底薪+件数）重写 <code>salary()</code></li>
<li>接口 <code>Flyable</code>/<code>Swimmable</code>，类 <code>Duck</code> 实现两个、<code>Plane</code> 只实现飞行，用多态数组演示</li>
<li>自定义 <code>Point</code> 类：正确重写 equals/hashCode/toString，放入 HashSet 验证去重</li>
<li>用接口 <code>Comparator&lt;T&gt;</code> 实现”按成绩降序”比较器（第六篇预告集合排序）</li>
<li>（概念）重载与重写的区别？接口与抽象类的区别？编译看左运行看右什么意思？</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>单继承 extends；super 必须第一行；构造先父后子</li>
<li>重写遵循”两同两小一大”；@Override 必写</li>
<li>多态 = 继承 + 重写 + 向上转型；编译看左、运行看右</li>
<li>抽象类是模板，接口是能力（可多实现）；面向接口编程 = 解耦</li>
<li>equals/hashCode/toString 三件套成对改写</li>
<li>final 可锁类/方法/变量</li>
</ul><p><strong>下一篇</strong>：常用类库——String 深入、包装类、日期时间与数学工具。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。接口优先的思维方式是读懂 Spring 全家源码的钥匙。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-07/</id>
      <title type="text">Java 入门教程（七）：核心类库——String、包装类与常用工具</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-07/"/>
      <summary type="text">深入 String 不可变性与常量池、StringBuffer 与 StringBuilder 选型、== 与 equals 的坑、包装类与自动装箱、Integer 缓存陷阱、BigDecimal 金额计算、LocalDateTime 新日期 API。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>日常 Java 开发 80% 的时间在和字符串、包装类、日期打交道。本篇把 JDK 自带的核心类库讲透——特别是那些”面试必考、实战必踩”的坑。</p></section>
<section><h2>一、String 深入<a href="#一string-深入"><span>#</span></a></h2><section><h3>不可变性（核心！）<a href="#不可变性核心"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span> s </span><span><span>=</span><span> </span></span><span>"hello"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>s</span><span>.</span><span>toUpperCase</span><span><span>();</span><span>          </span></span><span>// 产生新对象 "HELLO"</span></div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(s);</span><span>    </span></span><span>// hello——原串纹丝不动！</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>s</span><span>.</span><span>toUpperCase</span><span><span>();</span><span>      </span></span><span>// ✓ 必须接住返回值</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>String 内部的字符数组是 final 的</strong>——任何”修改”操作都返回新对象。好处：线程安全、可作 HashMap 的键、字符串常量池可复用。</p></section><section><h3>常量池与 == 的坑（面试 TOP3）<a href="#常量池与--的坑面试-top3"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 字面量赋值：进常量池，同字面量共享一个对象</span></div></div><div><div><div>2</div></div><div><span>String</span><span> a </span><span><span>=</span><span> </span></span><span>"hello"</span><span>;</span></div></div><div><div><div>3</div></div><div><span>String</span><span> b </span><span><span>=</span><span> </span></span><span>"hello"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> b);</span><span>         </span></span><span>// true（常量池同一对象）</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// new 出来的：堆里新对象</span></div></div><div><div><div>7</div></div><div><span>String</span><span> c </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>String</span><span>(</span><span>"hello"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> c);</span><span>         </span></span><span>// false（地址不同！）</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>.</span><span>equals</span><span><span>(c));</span><span>    </span></span><span>// true（内容相同）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 拼接陷阱：编译期能确定的进池，运行期拼接产生新对象</span></div></div><div><div><div>12</div></div><div><span>String</span><span> d </span><span><span>=</span><span> </span></span><span>"hel"</span><span><span> </span><span>+</span><span> </span></span><span>"lo"</span><span><span>;</span><span>            </span></span><span>// 编译期合并</span></div></div><div><div><div>13</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> d);</span><span>         </span></span><span>// true</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>String</span><span> part </span><span><span>=</span><span> </span></span><span>"lo"</span><span>;</span></div></div><div><div><div>16</div></div><div><span>String</span><span> e </span><span><span>=</span><span> </span></span><span>"hel"</span><span><span> </span><span>+</span><span> part</span><span>;</span><span>            </span></span><span>// 运行期拼接</span></div></div><div><div><div>17</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> e);</span><span>         </span></span><span>// false！</span></div></div><div><div><div>18</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> </span></span><span>e</span><span>.</span><span>intern</span><span>());</span><span>// true（intern 取常量池版本）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>铁律：字符串内容比较永远用 equals，== 只用来判断”是不是同一个对象”</strong>。</p></section><section><h3>常用方法全家桶<a href="#常用方法全家桶"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span> s </span><span><span>=</span><span> </span></span><span>"  Hello, Java World  "</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>length</span><span><span>());</span><span>              </span></span><span>// 20</span></div></div><div><div><div>4</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>trim</span><span><span>());</span><span>                </span></span><span>// 去两端空白 "Hello, Java World"</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>strip</span><span><span>());</span><span>               </span></span><span>// Java 11+（还能处理全角空格）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>charAt</span><span>(</span><span>1</span><span><span>));</span><span>             </span></span><span>// 'H'</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>indexOf</span><span>(</span><span>"Java"</span><span><span>));</span><span>       </span></span><span>// 8</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>contains</span><span>(</span><span>"Java"</span><span><span>));</span><span>      </span></span><span>// true</span></div></div><div><div><div>10</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>startsWith</span><span>(</span><span>"  He"</span><span><span>));</span><span>    </span></span><span>// true</span></div></div><div><div><div>11</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>endsWith</span><span>(</span><span>"  "</span><span><span>));</span><span>        </span></span><span>// true</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>substring</span><span>(</span><span>8</span><span>, </span><span>12</span><span><span>));</span><span>      </span></span><span>// "Java"（含头不含尾）</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>s</span><span>.</span><span>replace</span><span>(</span><span>"Java"</span><span>, </span><span>"Python"</span><span>));</span></div></div><div><div><div>15</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"a,b,c"</span><span>.</span><span>split</span><span>(</span><span>","</span><span>).</span><span>length</span><span><span>);</span><span>       </span></span><span>// 3</span></div></div><div><div><div>16</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"ab"</span><span>.</span><span>repeat</span><span>(</span><span>3</span><span><span>));</span><span>          </span></span><span>// ababab（Java 11+）</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"abc"</span><span>.</span><span>toUpperCase</span><span>());</span></div></div><div><div><div>19</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"ABC"</span><span>.</span><span>toLowerCase</span><span>());</span></div></div><div><div><div>20</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>""</span><span>.</span><span>isEmpty</span><span><span>());</span><span>            </span></span><span>// true</span></div></div><div><div><div>21</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"  "</span><span>.</span><span>isBlank</span><span><span>());</span><span>          </span></span><span>// true（Java 11+ 纯空白）</span></div></div><div><div><div>22</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>String</span><span>.</span><span>join</span><span>(</span><span>"-"</span><span>, </span><span>"2026"</span><span>, </span><span>"10"</span><span>, </span><span>"29"</span><span><span>));</span><span>  </span></span><span>// 2026-10-29</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>// 文本块（Java 15+）：多行字符串</span></div></div><div><div><div>25</div></div><div><span>String</span><span> json </span><span><span>=</span><span> </span></span><span>"""</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>{</span></div></div><div><div><div>27</div></div><div><span><span>          </span></span><span>"name": "小明",</span></div></div><div><div><div>28</div></div><div><span><span>          </span></span><span>"age": 18</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>}"""</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>判等空串与 null 的正确姿势<a href="#判等空串与-null-的正确姿势"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span> input </span><span><span>=</span><span> </span></span><span>/* 可能为 null */</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// ❌ if (input.equals("")) → NPE 空指针</span></div></div><div><div><div>4</div></div><div><span>// ✅ 常量放前面 / 先判 null</span></div></div><div><div><div>5</div></div><div><span>if</span><span><span> (input </span><span>==</span><span> </span></span><span>null</span><span><span> </span><span>||</span><span> </span></span><span>input</span><span>.</span><span>isEmpty</span><span><span>()</span><span>) { }</span></span></div></div><div><div><div>6</div></div><div><span>if</span><span><span> (input </span><span>!=</span><span> </span></span><span>null</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>"yes"</span><span>.</span><span>equals</span><span><span>(input)</span><span>) { }    </span></span><span>// 常量在前防 NPE</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>StringBuilder：循环拼接必用<a href="#stringbuilder循环拼接必用"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ❌ 循环里 + 拼接：每次循环产生新 String 对象，O(n²)</span></div></div><div><div><div>2</div></div><div><span>String</span><span> result </span><span><span>=</span><span> </span></span><span>""</span><span>;</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>10000</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>result </span><span>+=</span><span> i</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// ✅ StringBuilder：内部可变字符数组，O(n)</span></div></div><div><div><div>8</div></div><div><span>StringBuilder</span><span> sb </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>StringBuilder</span><span><span>()</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>10000</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>sb</span><span>.</span><span>append</span><span>(i);</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>String</span><span> fast </span><span><span>=</span><span> </span></span><span>sb</span><span>.</span><span>toString</span><span>();</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>sb</span><span>.</span><span>append</span><span>(</span><span>"-"</span><span>).</span><span>append</span><span>(</span><span>42</span><span>).</span><span>append</span><span>(</span><span>"!"</span><span><span>);</span><span>    </span></span><span>// 链式</span></div></div><div><div><div>15</div></div><div><span>sb</span><span>.</span><span>insert</span><span>(</span><span>0</span><span>, </span><span>"头"</span><span>);</span></div></div><div><div><div>16</div></div><div><span>sb</span><span>.</span><span>deleteCharAt</span><span>(</span><span>sb</span><span>.</span><span>length</span><span><span>() </span><span>-</span><span> </span></span><span>1</span><span>);</span></div></div><div><div><div>17</div></div><div><span>sb</span><span>.</span><span>reverse</span><span><span>();</span><span>                             </span></span><span>// 反转</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>

<table><thead><tr><th>类</th><th>可变</th><th>线程安全</th><th>场景</th></tr></thead><tbody><tr><td>String</td><td>✗</td><td>✓（不可变天然安全）</td><td>绝大多数场景</td></tr><tr><td>StringBuilder</td><td>✓</td><td>✗</td><td><strong>单线程拼接（默认）</strong></td></tr><tr><td>StringBuffer</td><td>✓</td><td>✓（synchronized）</td><td>多线程（如今少见）</td></tr></tbody></table></section></section>
<section><h2>二、包装类<a href="#二包装类"><span>#</span></a></h2><section><h3>基本类型 ↔ 包装类<a href="#基本类型--包装类"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> → </span><span>Integer</span><span>     </span><span>double</span><span> → </span><span>Double</span><span>     </span><span>char</span><span> → </span><span>Character</span></div></div><div><div><div>2</div></div><div><span>long</span><span> → </span><span>Long</span><span>       </span><span>boolean</span><span> → </span><span>Boolean</span><span><span>  </span><span>...</span><span>（其余同名首字母大写）</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 自动装箱/拆箱（编译器语法糖）</span></div></div><div><div><div>5</div></div><div><span>Integer</span><span> boxed </span><span><span>=</span><span> </span></span><span>42</span><span><span>;</span><span>            </span></span><span>// 装箱：Integer.valueOf(42)</span></div></div><div><div><div>6</div></div><div><span>int</span><span> raw </span><span><span>=</span><span> boxed</span><span>;</span><span>               </span></span><span>// 拆箱：boxed.intValue()</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 手动转换</span></div></div><div><div><div>9</div></div><div><span>Integer</span><span> m </span><span><span>=</span><span> </span></span><span>Integer</span><span>.</span><span>valueOf</span><span>(</span><span>42</span><span>);</span></div></div><div><div><div>10</div></div><div><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>m</span><span>.</span><span>intValue</span><span>();</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 字符串互转（高频！）</span></div></div><div><div><div>13</div></div><div><span>int</span><span> age </span><span><span>=</span><span> </span></span><span>Integer</span><span>.</span><span>parseInt</span><span>(</span><span>"18"</span><span><span>);</span><span>          </span></span><span>// String → int</span></div></div><div><div><div>14</div></div><div><span>double</span><span> d </span><span><span>=</span><span> </span></span><span>Double</span><span>.</span><span>parseDouble</span><span>(</span><span>"3.14"</span><span>);</span></div></div><div><div><div>15</div></div><div><span>String</span><span> s </span><span><span>=</span><span> </span></span><span>String</span><span>.</span><span>valueOf</span><span>(</span><span>42</span><span><span>);</span><span>             </span></span><span>// 数 → String</span></div></div><div><div><div>16</div></div><div><span>String</span><span> t </span><span><span>=</span><span> </span></span><span>Integer</span><span>.</span><span>toString</span><span>(</span><span>42</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>Integer 缓存陷阱（面试 TOP1）<a href="#integer-缓存陷阱面试-top1"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Integer</span><span> a </span><span><span>=</span><span> </span></span><span>127</span><span><span>,</span><span> b </span><span>=</span><span> </span></span><span>127</span><span>;</span></div></div><div><div><div>2</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(a </span><span>==</span><span> b);</span><span>        </span></span><span>// true（-128~127 有缓存，同一对象）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>Integer</span><span> c </span><span><span>=</span><span> </span></span><span>128</span><span><span>,</span><span> d </span><span>=</span><span> </span></span><span>128</span><span>;</span></div></div><div><div><div>5</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(c </span><span>==</span><span> d);</span><span>        </span></span><span>// false！超出缓存范围，各自 new</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>c</span><span>.</span><span>equals</span><span><span>(d));</span><span>   </span></span><span>// true</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 铁律：包装类比较一律 equals</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>拆箱空指针：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Integer</span><span> score </span><span><span>=</span><span> </span></span><span>null</span><span>;</span></div></div><div><div><div>2</div></div><div><span>int</span><span> s </span><span><span>=</span><span> score</span><span>;</span><span>        </span></span><span>// ❌ NullPointerException（null 拆箱炸）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>数据库字段/外部输入可能为 null 时，用 <code>Integer</code> 并先判空。</p></div></div></section></section>
<section><h2>三、BigDecimal：金额计算唯一正解<a href="#三bigdecimal金额计算唯一正解"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.math.BigDecimal</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.math.RoundingMode</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// ⚠ 别用 new BigDecimal(0.1)——浮点误差原样带入！</span></div></div><div><div><div>5</div></div><div><span>BigDecimal</span><span> a </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"0.1"</span><span><span>)</span><span>;</span><span>           </span></span><span>// ✓ 用字符串构造</span></div></div><div><div><div>6</div></div><div><span>BigDecimal</span><span> b </span><span><span>=</span><span> </span></span><span>BigDecimal</span><span>.</span><span>valueOf</span><span>(</span><span>0.1</span><span><span>);</span><span>         </span></span><span>// ✓ 或 valueOf</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>a</span><span>.</span><span>add</span><span><span>(b));</span><span>                    </span></span><span>// 0.2（精确！）</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"10"</span><span>).</span><span>divide</span><span>(</span></div></div><div><div><div>10</div></div><div><span>        </span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"3"</span><span>), </span><span>2</span><span>, </span><span>RoundingMode</span><span>.</span><span>HALF_UP</span><span><span>));</span><span>   </span></span><span>// 3.33</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 比较用 compareTo（equals 会连精度一起比：1.0 != 1.00）</span></div></div><div><div><div>13</div></div><div><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"1.0"</span><span><span>)</span><span>.</span></span><span>compareTo</span><span>(</span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"1.00"</span><span><span>));</span><span>  </span></span><span>// 0（相等）</span></div></div><div><div><div>14</div></div><div><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"1.0"</span><span><span>)</span><span>.</span></span><span>equals</span><span>(</span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"1.00"</span><span><span>));</span><span>     </span></span><span>// false！</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// 金额展示</span></div></div><div><div><div>17</div></div><div><span>BigDecimal</span><span> price </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"99.999"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>price</span><span>.</span><span>setScale</span><span>(</span><span>2</span><span>, </span><span>RoundingMode</span><span>.</span><span>HALF_UP</span><span><span>));</span><span>   </span></span><span>// 100.00</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>四、日期时间（java.time，Java 8+）<a href="#四日期时间javatimejava-8"><span>#</span></a></h2><blockquote><p>老的 <code>Date</code>/<code>SimpleDateFormat</code> 有线程安全与设计问题，<strong>新项目一律用 java.time</strong>。</p></blockquote><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.time.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.time.format.DateTimeFormatter</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// —— 三大核心类型 ——</span></div></div><div><div><div>5</div></div><div><span>LocalDate</span><span> date </span><span><span>=</span><span> </span></span><span>LocalDate</span><span>.</span><span>now</span><span><span>();</span><span>               </span></span><span>// 2026-10-29（仅日期）</span></div></div><div><div><div>6</div></div><div><span>LocalTime</span><span> time </span><span><span>=</span><span> </span></span><span>LocalTime</span><span>.</span><span>now</span><span><span>();</span><span>               </span></span><span>// 12:30:45.123（仅时间）</span></div></div><div><div><div>7</div></div><div><span>LocalDateTime</span><span> dt </span><span><span>=</span><span> </span></span><span>LocalDateTime</span><span>.</span><span>now</span><span><span>();</span><span>         </span></span><span>// 日期+时间</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>LocalDate</span><span> birthday </span><span><span>=</span><span> </span></span><span>LocalDate</span><span>.</span><span>of</span><span>(</span><span>2006</span><span>, </span><span>6</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>10</div></div><div><span>LocalDateTime</span><span> specific </span><span><span>=</span><span> </span></span><span>LocalDateTime</span><span>.</span><span>of</span><span>(</span><span>2026</span><span>, </span><span>10</span><span>, </span><span>29</span><span>, </span><span>14</span><span>, </span><span>30</span><span>);</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// —— 格式化与解析 ——</span></div></div><div><div><div>13</div></div><div><span>DateTimeFormatter</span><span> fmt </span><span><span>=</span><span> </span></span><span>DateTimeFormatter</span><span>.</span><span>ofPattern</span><span>(</span><span>"yyyy年MM月dd日 HH:mm:ss"</span><span>);</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>dt</span><span>.</span><span>format</span><span><span>(fmt));</span><span>              </span></span><span>// 2026年10月29日 12:30:45</span></div></div><div><div><div>15</div></div><div><span>LocalDateTime</span><span> parsed </span><span><span>=</span><span> </span></span><span>LocalDateTime</span><span>.</span><span>parse</span><span>(</span><span>"2026-10-29 14:30:00"</span><span>,</span></div></div><div><div><div>16</div></div><div><span>        </span><span>DateTimeFormatter</span><span>.</span><span>ofPattern</span><span>(</span><span>"yyyy-MM-dd HH:mm:ss"</span><span>));</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>// —— 计算 ——</span></div></div><div><div><div>19</div></div><div><span>LocalDate</span><span> tomorrow </span><span><span>=</span><span> </span></span><span>date</span><span>.</span><span>plusDays</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>20</div></div><div><span>LocalDate</span><span> lastMonth </span><span><span>=</span><span> </span></span><span>date</span><span>.</span><span>minusMonths</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>21</div></div><div><span>LocalDate</span><span> nextYearSameDay </span><span><span>=</span><span> </span></span><span>date</span><span>.</span><span>plusYears</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>Period</span><span> age </span><span><span>=</span><span> </span></span><span>Period</span><span>.</span><span>between</span><span>(birthday, date);</span></div></div><div><div><div>24</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%d 岁 %d 个月%n"</span><span>, </span><span>age</span><span>.</span><span>getYears</span><span>(), </span><span>age</span><span>.</span><span>getMonths</span><span>());</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>long</span><span> days </span><span><span>=</span><span> </span></span><span>java</span><span>.</span><span>time</span><span>.</span><span>temporal</span><span>.</span><span>ChronoUnit</span><span>.</span><span>DAYS</span><span>.</span><span>between</span><span>(birthday, date);</span></div></div><div><div><div>27</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"活了 "</span><span><span> </span><span>+</span><span> days </span><span>+</span><span> </span></span><span>" 天"</span><span>);</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>// 判断</span></div></div><div><div><div>30</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>date</span><span>.</span><span>isBefore</span><span><span>(tomorrow));</span><span>     </span></span><span>// true</span></div></div><div><div><div>31</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>date</span><span>.</span><span>isLeapYear</span><span><span>());</span><span>           </span></span><span>// 闰年判断</span></div></div><div><div><div>32</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>date</span><span>.</span><span>getDayOfWeek</span><span><span>());</span><span>         </span></span><span>// THURSDAY</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>// —— 时间戳互转 ——</span></div></div><div><div><div>35</div></div><div><span>Instant</span><span> now </span><span><span>=</span><span> </span></span><span>Instant</span><span>.</span><span>now</span><span><span>();</span><span>                     </span></span><span>// UTC 时间戳</span></div></div><div><div><div>36</div></div><div><span>long</span><span> epochMilli </span><span><span>=</span><span> </span></span><span>now</span><span>.</span><span>toEpochMilli</span><span><span>();</span><span>            </span></span><span>// 毫秒时间戳</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>五、其他高频工具<a href="#五其他高频工具"><span>#</span></a></h2><section><h3>Objects 工具类<a href="#objects-工具类"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Objects</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>Objects</span><span>.</span><span>equals</span><span><span>(a, b);</span><span>            </span></span><span>// null 安全的判等</span></div></div><div><div><div>4</div></div><div><span>Objects</span><span>.</span><span>isNull</span><span><span>(x);</span><span>               </span></span><span>// x == null</span></div></div><div><div><div>5</div></div><div><span>Objects</span><span>.</span><span>requireNonNull</span><span>(param, </span><span>"参数不能为空"</span><span><span>);</span><span>   </span></span><span>// 快速判空抛 NPE</span></div></div><div><div><div>6</div></div><div><span>Objects</span><span>.</span><span>hashCode</span><span>(x);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>数组与集合桥梁（预热下一篇）<a href="#数组与集合桥梁预热下一篇"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span>[] arr </span><span><span>=</span><span> {</span></span><span>3</span><span><span>,</span><span> </span></span><span>1</span><span><span>,</span><span> </span></span><span>4</span><span><span>}</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span>int</span><span>[] copy </span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>copyOf</span><span>(arr, </span><span>arr</span><span>.</span><span>length</span><span>);</span></div></div><div><div><div>3</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> list </span></span><span><span>=</span><span> </span></span><span>Arrays</span><span>.</span><span>asList</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span><span>);</span><span>       </span></span><span>// 固定长度视图</span></div></div><div><div><div>4</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> mutable </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span><span>)</span><span>)</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、综合案例：会员账单生成器<a href="#六综合案例会员账单生成器"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.math.BigDecimal</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.math.RoundingMode</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>java.time.LocalDateTime</span><span>;</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>java.time.format.DateTimeFormatter</span><span>;</span></div></div><div><div><div>5</div></div><div><span>import</span><span> </span><span>java.util.StringJoiner</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Bill</span><span> </span></span><span>{</span></div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>String</span><span><span> </span><span>name</span><span> </span></span><span><span>=</span><span> </span></span><span>"小明"</span><span>;</span></div></div><div><div><div>10</div></div><div><span>        </span><span>BigDecimal</span><span><span> </span><span>vipRate</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BigDecimal</span><span>(</span><span>"0.88"</span><span>);</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>        </span><span>String</span><span><span>[][] </span><span>items</span><span> </span></span><span><span>=</span><span> {          </span></span><span>// [名称, 单价, 数量]</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>{</span><span>"机械键盘"</span><span>, </span><span>"399"</span><span>, </span><span>"1"</span><span>},</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>{</span><span>"鼠标垫"</span><span>, </span><span>"49.9"</span><span>, </span><span>"2"</span><span>},</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>{</span><span>"显示器支架"</span><span>, </span><span>"159"</span><span>, </span><span>"1"</span><span>},</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>};</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>        </span><span>BigDecimal</span><span><span> </span><span>total</span><span> </span></span><span><span>=</span><span> </span></span><span>BigDecimal</span><span>.</span><span>ZERO</span><span>;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>StringJoiner</span><span><span> </span><span>lines</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>StringJoiner</span><span>(</span><span>"</span><span>\n</span><span>"</span><span>);    </span><span>// 拼接利器</span></div></div><div><div><div>20</div></div><div><span>        </span><span>for</span><span> (</span><span>String</span><span><span>[] </span><span>it</span><span> </span></span><span>:</span><span> items) {</span></div></div><div><div><div>21</div></div><div><span>            </span><span>BigDecimal</span><span><span> </span><span>line</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BigDecimal</span><span>(it[</span><span>1</span><span>])</span></div></div><div><div><div>22</div></div><div><span><span>                    </span></span><span>.</span><span>multiply</span><span>(</span><span>new</span><span> </span><span>BigDecimal</span><span>(it[</span><span>2</span><span>]));</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>total </span><span>=</span><span> </span><span>total</span><span>.</span><span>add</span><span>(line);</span></div></div><div><div><div>24</div></div><div><span>            </span><span>lines</span><span>.</span><span>add</span><span>(</span><span>String</span><span>.</span><span>format</span><span>(</span><span>"%s × %s = ¥%s"</span><span>, it[</span><span>0</span><span>], it[</span><span>2</span><span>],</span></div></div><div><div><div>25</div></div><div><span>                    </span><span>line</span><span>.</span><span>setScale</span><span>(</span><span>2</span><span>, </span><span>RoundingMode</span><span>.</span><span>HALF_UP</span><span>)));</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>        </span><span>BigDecimal</span><span><span> </span><span>pay</span><span> </span></span><span><span>=</span><span> </span></span><span>total</span><span>.</span><span>multiply</span><span>(vipRate)</span></div></div><div><div><div>29</div></div><div><span><span>                </span></span><span>.</span><span>setScale</span><span>(</span><span>2</span><span>, </span><span>RoundingMode</span><span>.</span><span>HALF_UP</span><span>);</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>        </span><span>String</span><span><span> </span><span>time</span><span> </span></span><span><span>=</span><span> </span></span><span>LocalDateTime</span><span>.</span><span>now</span><span>()</span></div></div><div><div><div>32</div></div><div><span><span>                </span></span><span>.</span><span>format</span><span>(</span><span>DateTimeFormatter</span><span>.</span><span>ofPattern</span><span>(</span><span>"yyyy-MM-dd HH:mm"</span><span>));</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"====== 消费账单 ======"</span><span>);</span></div></div><div><div><div>35</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(lines);</span></div></div><div><div><div>36</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"----------------------"</span><span>);</span></div></div><div><div><div>37</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"合计: ¥%s%n"</span><span>, total);</span></div></div><div><div><div>38</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"VIP 88折: ¥%s%n"</span><span>, pay);</span></div></div><div><div><div>39</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"时间: "</span><span><span> </span><span>+</span><span> time);</span></span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>41</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>统计字符串中每个字符出现次数，按次数降序输出（Map + 排序预热）</li>
<li>反转字符串中的单词顺序（“hello java world” → “world java hello”；split + StringBuilder）</li>
<li>验证 Integer 缓存：循环比较 -200~200 的装箱 == 结果，统计 true 的范围</li>
<li>用 BigDecimal 计算”等额本息月供”：本金 100 万、年利率 3.6%、30 年（公式查资料，重点练 API）</li>
<li>写”倒计时日历”：输入目标日期字符串，输出距今多少天（LocalDate + ChronoUnit）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>String 不可变；内容比较永远 equals；常量池与 == 的关系要懂</li>
<li>循环拼接用 StringBuilder；StringJoiner 处理分隔符</li>
<li>包装类比较一律 equals（Integer 缓存 -128~127）；拆箱 null 会 NPE</li>
<li>金额计算只信 BigDecimal（字符串构造 + compareTo 比较）</li>
<li>日期新 API：LocalDateTime + DateTimeFormatter + Period/ChronoUnit</li>
</ul><p><strong>下一篇</strong>：集合框架——ArrayList/HashMap 全家桶，Java 数据处理的发动机。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。String 的 == 陷阱与 Integer 缓存是笔试最爱，亲手跑一遍记住结论。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-08/</id>
      <title type="text">Java 入门教程（八）：集合框架</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-08/"/>
      <summary type="text">系统讲解 Java 集合体系：List（ArrayList/LinkedList）、Set（HashSet/TreeSet/LinkedHashSet）、Map（HashMap/TreeMap）核心操作与选型、迭代与 fail-fast、Comparable 与 Comparator 排序、集合工具类，附词频统计与成绩系统案例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>数组定长，集合（Collection）动态——Java 集合框架是日常开发的绝对主力（前几篇已偷偷用过 ArrayList）。本篇系统讲透 List/Set/Map 三大体系与排序方案。</p></section>
<section><h2>一、集合体系全景<a href="#一集合体系全景"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Collection（接口）</span></div></div><div><div><div>2</div></div><div><span>├── List   有序可重复</span></div></div><div><div><div>3</div></div><div><span>│   ├── ArrayList      动态数组（默认选择）</span></div></div><div><div><div>4</div></div><div><span>│   └── LinkedList     双向链表</span></div></div><div><div><div>5</div></div><div><span>├── Set    不可重复</span></div></div><div><div><div>6</div></div><div><span>│   ├── HashSet        哈希（最快，无序）</span></div></div><div><div><div>7</div></div><div><span>│   ├── LinkedHashSet  哈希 + 保插入序</span></div></div><div><div><div>8</div></div><div><span>│   └── TreeSet        红黑树（自动排序）</span></div></div><div><div><div>9</div></div><div><span>└── Queue  队列（了解）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>Map（接口，独立于 Collection）</span></div></div><div><div><div>12</div></div><div><span>├── HashMap           哈希键值对（默认选择）</span></div></div><div><div><div>13</div></div><div><span>├── LinkedHashMap     保插入序</span></div></div><div><div><div>14</div></div><div><span>└── TreeMap           按键排序</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>泛型 <code>&lt;T&gt;</code></strong>：集合声明元素类型，编译期防类型错误——<code>List&lt;String&gt;</code> 只能装 String。</p></section>
<section><h2>二、List<a href="#二list"><span>#</span></a></h2><section><h3>ArrayList（默认选择）<a href="#arraylist默认选择"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.ArrayList</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> langs </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// —— 增 ——</span></div></div><div><div><div>7</div></div><div><span>langs</span><span>.</span><span>add</span><span>(</span><span>"Java"</span><span><span>);</span><span>                       </span></span><span>// 尾部追加</span></div></div><div><div><div>8</div></div><div><span>langs</span><span>.</span><span>add</span><span>(</span><span>0</span><span>, </span><span>"C++"</span><span><span>);</span><span>                     </span></span><span>// 指定位置（O(n)）</span></div></div><div><div><div>9</div></div><div><span>langs</span><span>.</span><span>addAll</span><span>(</span><span>List</span><span>.</span><span>of</span><span>(</span><span>"Python"</span><span>, </span><span>"Go"</span><span><span>));</span><span>   </span></span><span>// 批量</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// —— 删 ——</span></div></div><div><div><div>12</div></div><div><span>langs</span><span>.</span><span>remove</span><span>(</span><span>"Go"</span><span><span>);</span><span>                      </span></span><span>// 按对象删第一个</span></div></div><div><div><div>13</div></div><div><span>langs</span><span>.</span><span>remove</span><span>(</span><span>0</span><span><span>);</span><span>                         </span></span><span>// 按下标删（返回被删元素）</span></div></div><div><div><div>14</div></div><div><span>langs</span><span>.</span><span>removeIf</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>startsWith</span><span>(</span><span>"P"</span><span><span>));</span><span>  </span></span><span>// 条件删除（Java 8+）</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// —— 改查 ——</span></div></div><div><div><div>17</div></div><div><span>langs</span><span>.</span><span>set</span><span>(</span><span>0</span><span>, </span><span>"Java17"</span><span>);</span></div></div><div><div><div>18</div></div><div><span>String</span><span> first </span><span><span>=</span><span> </span></span><span>langs</span><span>.</span><span>get</span><span>(</span><span>0</span><span><span>);</span><span>             </span></span><span>// O(1) 随机访问</span></div></div><div><div><div>19</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>langs</span><span>.</span><span>contains</span><span>(</span><span>"C++"</span><span>));</span></div></div><div><div><div>20</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>langs</span><span>.</span><span>indexOf</span><span>(</span><span>"Java"</span><span>));</span></div></div><div><div><div>21</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>langs</span><span>.</span><span>size</span><span>());</span></div></div><div><div><div>22</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>langs</span><span>.</span><span>isEmpty</span><span>());</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>// —— 遍历 ——</span></div></div><div><div><div>25</div></div><div><span>for</span><span> (</span><span>String</span><span> lang </span><span>:</span><span> langs) { }                    </span><span>// 增强 for</span></div></div><div><div><div>26</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>langs</span><span>.</span><span>size</span><span><span>();</span><span> i</span><span>++</span><span>) { }       </span></span><span>// 下标</span></div></div><div><div><div>27</div></div><div><span>langs</span><span>.</span><span>forEach</span><span>(s </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(s));</span><span>       </span></span><span>// 函数式</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>// —— 不可变集合（Java 9+）——</span></div></div><div><div><div>30</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> frozen </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>"a"</span><span>, </span><span>"b"</span><span><span>);</span><span>         </span></span><span>// 不可增删改！</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>ArrayList vs LinkedList<a href="#arraylist-vs-linkedlist"><span>#</span></a></h3>

<table><thead><tr><th></th><th>ArrayList</th><th>LinkedList</th></tr></thead><tbody><tr><td>随机访问</td><td>O(1)</td><td>O(n)</td></tr><tr><td>尾部增删</td><td>均摊 O(1)</td><td>O(1)</td></tr><tr><td>中间增删</td><td>O(n)</td><td>定位 O(n) + 修改 O(1)</td></tr><tr><td>实践建议</td><td><strong>99% 场景</strong></td><td>极少胜出</td></tr></tbody></table></section><section><h3>安全删除：ConcurrentModificationException<a href="#安全删除concurrentmodificationexception"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> nums </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span><span>)</span><span>)</span><span>;</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// ❌ 遍历中直接 remove → ConcurrentModificationException（fail-fast）</span></div></div><div><div><div>4</div></div><div><span>// for (Integer n : nums) { if (n % 2 == 0) nums.remove(n); }</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// ✅ 三种正确姿势</span></div></div><div><div><div>7</div></div><div><span>nums</span><span>.</span><span>removeIf</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span><span>);</span><span>                       </span></span><span>// ① 条件删除（最简）</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>Iterator</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> it </span></span><span><span>=</span><span> </span></span><span>nums</span><span>.</span><span>iterator</span><span><span>();</span><span> </span></span><span>it</span><span>.</span><span>hasNext</span><span><span>();</span><span> ) {   </span></span><span>// ② 迭代器</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span> (</span><span>it</span><span>.</span><span>next</span><span><span>()</span><span> </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>) </span><span>it</span><span>.</span><span>remove</span><span>();</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>// ③ 倒序下标循环（正序会跳元素）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、Set<a href="#三set"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// HashSet：去重最快（依赖 hashCode/equals）</span></div></div><div><div><div>4</div></div><div><span>Set</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> tags </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>HashSet</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>tags</span><span>.</span><span>add</span><span>(</span><span>"java"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>tags</span><span>.</span><span>add</span><span>(</span><span>"python"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>tags</span><span>.</span><span>add</span><span>(</span><span>"java"</span><span><span>);</span><span>                         </span></span><span>// 重复添加被忽略</span></div></div><div><div><div>8</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>tags</span><span>.</span><span>size</span><span><span>());</span><span>          </span></span><span>// 2</span></div></div><div><div><div>9</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>tags</span><span>.</span><span>contains</span><span>(</span><span>"java"</span><span><span>));</span><span> </span></span><span>// true</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 列表去重一行流</span></div></div><div><div><div>12</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> dup </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>3</span><span>, </span><span>1</span><span>, </span><span>3</span><span>, </span><span>2</span><span>, </span><span>1</span><span><span>)</span><span>)</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span>Set</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> uniq </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>LinkedHashSet</span><span><span>&lt;&gt;</span><span>(dup)</span><span>;</span><span>    </span></span><span>// 保序去重</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(uniq);</span><span>                 </span></span><span>// [3, 1, 2]</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// TreeSet：自动排序</span></div></div><div><div><div>17</div></div><div><span>Set</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> sorted </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>TreeSet</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>5</span><span>, </span><span>1</span><span>, </span><span>4</span><span><span>)</span><span>)</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(sorted);</span><span>               </span></span><span>// [1, 4, 5]</span></div></div><div><div><div>19</div></div><div><span>// 首尾与范围</span></div></div><div><div><div>20</div></div><div><span>TreeSet</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> ts </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>TreeSet</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>3</span><span>, </span><span>5</span><span>, </span><span>7</span><span>, </span><span>9</span><span><span>)</span><span>)</span><span>;</span></span></div></div><div><div><div>21</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ts</span><span>.</span><span>first</span><span><span>() </span><span>+</span><span> </span></span><span>" "</span><span><span> </span><span>+</span><span> </span></span><span>ts</span><span>.</span><span>last</span><span><span>());</span><span>   </span></span><span>// 1 9</span></div></div><div><div><div>22</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ts</span><span>.</span><span>headSet</span><span>(</span><span>5</span><span><span>));</span><span>       </span></span><span>// [1, 3]（小于5）</span></div></div><div><div><div>23</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ts</span><span>.</span><span>tailSet</span><span>(</span><span>5</span><span><span>));</span><span>       </span></span><span>// [5, 7, 9]</span></div></div><div><div><div>24</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ts</span><span>.</span><span>floor</span><span>(</span><span>6</span><span><span>));</span><span>         </span></span><span>// 5（≤6 的最大）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>自定义对象入 HashSet/HashMap 的前提</strong>：正确重写 <code>hashCode</code> + <code>equals</code>（第六篇）——忘了重写，“相等”的两个对象会被当成两个存两份。</p></section>
<section><h2>四、Map<a href="#四map"><span>#</span></a></h2><section><h3>HashMap（默认选择）<a href="#hashmap默认选择"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.HashMap</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.Map</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> ages </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>HashMap</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// —— 增改 ——</span></div></div><div><div><div>7</div></div><div><span>ages</span><span>.</span><span>put</span><span>(</span><span>"小明"</span><span>, </span><span>18</span><span><span>);</span><span>                     </span></span><span>// 不存在则增，存在则改（返回旧值！）</span></div></div><div><div><div>8</div></div><div><span>ages</span><span>.</span><span>putIfAbsent</span><span>(</span><span>"小红"</span><span>, </span><span>17</span><span><span>);</span><span>             </span></span><span>// 不存在才放</span></div></div><div><div><div>9</div></div><div><span>ages</span><span>.</span><span>put</span><span>(</span><span>"小明"</span><span>, </span><span>19</span><span><span>);</span><span>                     </span></span><span>// 覆盖为 19</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// —— 查 ——</span></div></div><div><div><div>12</div></div><div><span>int</span><span> age </span><span><span>=</span><span> </span></span><span>ages</span><span>.</span><span>get</span><span>(</span><span>"小明"</span><span><span>);</span><span>               </span></span><span>// 19</span></div></div><div><div><div>13</div></div><div><span>Integer</span><span> none </span><span><span>=</span><span> </span></span><span>ages</span><span>.</span><span>get</span><span>(</span><span>"不存在"</span><span><span>);</span><span>        </span></span><span>// null</span></div></div><div><div><div>14</div></div><div><span>int</span><span> def </span><span><span>=</span><span> </span></span><span>ages</span><span>.</span><span>getOrDefault</span><span>(</span><span>"不存在"</span><span>, </span><span>0</span><span><span>);</span><span> </span></span><span>// 0（推荐！防 null）</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ages</span><span>.</span><span>containsKey</span><span>(</span><span>"小明"</span><span>));</span></div></div><div><div><div>17</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>ages</span><span>.</span><span>containsValue</span><span>(</span><span>19</span><span>));</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>// —— 删 ——</span></div></div><div><div><div>20</div></div><div><span>ages</span><span>.</span><span>remove</span><span>(</span><span>"小红"</span><span>);</span></div></div><div><div><div>21</div></div><div><span>ages</span><span>.</span><span>remove</span><span>(</span><span>"小明"</span><span>, </span><span>19</span><span><span>);</span><span>                  </span></span><span>// 键值都对上才删</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>// —— 遍历三式 ——</span></div></div><div><div><div>24</div></div><div><span>for</span><span> (</span><span>String</span><span> key </span><span>:</span><span> </span><span>ages</span><span>.</span><span>keySet</span><span><span>()</span><span>) { }                  </span></span><span>// 遍历键</span></div></div><div><div><div>25</div></div><div><span>for</span><span> (</span><span>Integer</span><span> val </span><span>:</span><span> </span><span>ages</span><span>.</span><span>values</span><span><span>()</span><span>) { }                 </span></span><span>// 遍历值</span></div></div><div><div><div>26</div></div><div><span>for</span><span> (</span><span>Map</span><span>.</span><span>Entry</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> e </span></span><span>:</span><span> </span><span>ages</span><span>.</span><span>entrySet</span><span><span>()</span><span>) </span></span><span>// 键值对（最常用）</span></div></div><div><div><div>27</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>e</span><span>.</span><span>getKey</span><span><span>() </span><span>+</span><span> </span></span><span>" = "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getValue</span><span>());</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>// Java 8+ 函数式遍历</span></div></div><div><div><div>30</div></div><div><span>ages</span><span>.</span><span>forEach</span><span>((k, v) </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(k </span><span>+</span><span> </span></span><span>":"</span><span><span> </span><span>+</span><span> v));</span></span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>// —— 统计利器 ——</span></div></div><div><div><div>33</div></div><div><span>ages</span><span>.</span><span>merge</span><span>(</span><span>"小明"</span><span>, </span><span>1</span><span>, Integer</span><span>::</span><span><span>sum);</span><span>      </span></span><span>// 计数器模式：旧值+1</span></div></div><div><div><div>34</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(ages);</span><span>                 </span></span><span>// {小明=20}</span></div></div><div><div><div>35</div></div><div><span>ages</span><span>.</span><span>computeIfAbsent</span><span>(</span><span>"列表"</span><span>, k </span><span>-&gt;</span><span> </span><span>new</span><span> </span><span>java</span><span>.</span><span>util</span><span>.</span><span>ArrayList</span><span>&lt;</span><span>String</span><span>&gt;())</span></div></div><div><div><div>36</div></div><div><span><span>     </span></span><span>.</span><span>add</span><span>(</span><span>"元素"</span><span><span>);</span><span>                        </span></span><span>// 多值 Map 的构建块</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>merge 计数器（词频统计一行核心）<a href="#merge-计数器词频统计一行核心"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span>[] words </span><span><span>=</span><span> </span></span><span>"the quick the lazy the dog"</span><span>.</span><span>split</span><span>(</span><span>" "</span><span>);</span></div></div><div><div><div>2</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> freq </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>HashMap</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>String</span><span> w </span><span>:</span><span> words) {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>freq</span><span>.</span><span>merge</span><span>(w, </span><span>1</span><span>, Integer</span><span>::</span><span><span>sum);</span><span>       </span></span><span>// 没有则放1，有则 +1</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(freq);</span><span>                 </span></span><span>// {the=3, quick=1, lazy=1, dog=1}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>HashMap vs TreeMap vs LinkedHashMap<a href="#hashmap-vs-treemap-vs-linkedhashmap"><span>#</span></a></h3>

<table><thead><tr><th></th><th>HashMap</th><th>LinkedHashMap</th><th>TreeMap</th></tr></thead><tbody><tr><td>查找</td><td>O(1)</td><td>O(1)</td><td>O(log n)</td></tr><tr><td>顺序</td><td>无</td><td>插入序</td><td>键排序</td></tr><tr><td>场景</td><td>默认</td><td>需保序（LRU）</td><td>范围查询/排序遍历</td></tr></tbody></table></section></section>
<section><h2>五、排序：Comparable 与 Comparator<a href="#五排序comparable-与-comparator"><span>#</span></a></h2><section><h3>Comparable：自然顺序（类自己定义）<a href="#comparable自然顺序类自己定义"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Student</span><span> </span></span><span>implements</span><span><span> </span><span>Comparable</span><span>&lt;</span><span>Student</span><span>&gt;</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>String</span><span> name</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> score</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>Student</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>, </span></span><span>int</span><span><span> </span><span>score</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>name</span><span><span> </span><span>=</span><span> name; </span></span><span>this</span><span>.</span><span>score</span><span><span> </span><span>=</span><span> score; }</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>compareTo</span><span>(</span><span>Student</span><span><span> </span><span>o</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>return</span><span> </span><span>Integer</span><span>.</span><span>compare</span><span>(</span><span>this</span><span>.</span><span>score</span><span>, </span><span>o</span><span>.</span><span>score</span><span>);   </span><span>// 升序（反过来即降序）</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>13</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>toString</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span><span> name </span><span>+</span><span> </span></span><span>":"</span><span><span> </span><span>+</span><span> score; }</span></span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Comparator：外部策略（灵活多变）<a href="#comparator外部策略灵活多变"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;</span><span> st </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span></div></div><div><div><div>4</div></div><div><span>        </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小明"</span><span>, </span><span>90</span><span>), </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小红"</span><span>, </span><span>92</span><span>),</span></div></div><div><div><div>5</div></div><div><span>        </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小刚"</span><span>, </span><span>85</span><span><span>))</span><span>)</span><span>;</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 策略1：按分数降序（匿名内部类老写法 → lambda 新写法）</span></div></div><div><div><div>8</div></div><div><span>st</span><span>.</span><span>sort</span><span>((a, b) </span><span>-&gt;</span><span> </span><span>b</span><span>.</span><span>score</span><span><span> </span><span>-</span><span> </span></span><span>a</span><span>.</span><span>score</span><span>);</span></div></div><div><div><div>9</div></div><div><span>st</span><span>.</span><span>sort</span><span>(</span><span>Comparator</span><span>.</span><span>comparingInt</span><span>((</span><span>Student</span><span> s) </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span>).</span><span>reversed</span><span>());</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 策略2：按姓名排序</span></div></div><div><div><div>12</div></div><div><span>st</span><span>.</span><span>sort</span><span>(</span><span>Comparator</span><span>.</span><span>comparing</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>));</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 策略3：多级排序（分数降序，同分按姓名升序）</span></div></div><div><div><div>15</div></div><div><span>st</span><span>.</span><span>sort</span><span>(</span><span>Comparator</span><span>.</span><span>comparingInt</span><span>((</span><span>Student</span><span> s) </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span>).</span><span>reversed</span><span>()</span></div></div><div><div><div>16</div></div><div><span><span>                  </span></span><span>.</span><span>thenComparing</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>));</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span><span>(st);</span><span>   </span></span><span>// [小红:92, 小明:90, 小刚:85]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>选择</strong>：类的”天生顺序”用 Comparable；临时/多种排序策略用 Comparator（组合万岁）。</p></section><section><h3>Collections 工具类<a href="#collections-工具类"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Collections</span><span>.</span><span>sort</span><span><span>(list);</span><span>                 </span></span><span>// = list.sort(null)</span></div></div><div><div><div>2</div></div><div><span>Collections</span><span>.</span><span>reverse</span><span>(list);</span></div></div><div><div><div>3</div></div><div><span>Collections</span><span>.</span><span>shuffle</span><span><span>(list);</span><span>              </span></span><span>// 随机打乱</span></div></div><div><div><div>4</div></div><div><span>Collections</span><span>.</span><span>max</span><span>(list);</span></div></div><div><div><div>5</div></div><div><span>Collections</span><span>.</span><span>frequency</span><span>(list, </span><span>"a"</span><span><span>);</span><span>       </span></span><span>// 出现次数</span></div></div><div><div><div>6</div></div><div><span>Collections</span><span>.</span><span>swap</span><span>(list, </span><span>0</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>7</div></div><div><span>Collections</span><span>.</span><span>unmodifiableList</span><span><span>(list);</span><span>     </span></span><span>// 不可变视图</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、综合案例：学生成绩管理系统<a href="#六综合案例学生成绩管理系统"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.stream.Collectors</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ScoreSystem</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>record</span><span> </span><span>Student</span><span>(</span><span>String</span><span><span> name</span><span>,</span><span> </span></span><span>String</span><span><span> clazz</span><span>,</span><span> </span></span><span>int</span><span><span> score) </span><span>{}</span><span>   </span></span><span>// Java 16+ 数据类</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>8</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt; </span><span>all</span><span> </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span></div></div><div><div><div>9</div></div><div><span>            </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小明"</span><span>, </span><span>"一班"</span><span>, </span><span>90</span><span>),</span></div></div><div><div><div>10</div></div><div><span>            </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小红"</span><span>, </span><span>"二班"</span><span>, </span><span>85</span><span>),</span></div></div><div><div><div>11</div></div><div><span>            </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小刚"</span><span>, </span><span>"一班"</span><span>, </span><span>92</span><span>),</span></div></div><div><div><div>12</div></div><div><span>            </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小美"</span><span>, </span><span>"二班"</span><span>, </span><span>78</span><span>),</span></div></div><div><div><div>13</div></div><div><span>            </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小强"</span><span>, </span><span>"一班"</span><span>, </span><span>66</span><span>)</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>);</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>        </span><span>// 1. 排行榜（多级排序）</span></div></div><div><div><div>17</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt; </span><span>rank</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span>&lt;&gt;(all);</span></div></div><div><div><div>18</div></div><div><span>        </span><span>rank</span><span>.</span><span>sort</span><span>(</span><span>Comparator</span><span>.</span><span>comparingInt</span><span>(Student</span><span>::</span><span>score).</span><span>reversed</span><span>());</span></div></div><div><div><div>19</div></div><div><span>        </span><span>rank</span><span>.</span><span>forEach</span><span>(s </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"  %s %s %d%n"</span><span>,</span></div></div><div><div><div>20</div></div><div><span>                </span><span>s</span><span>.</span><span>name</span><span>(), </span><span>s</span><span>.</span><span>clazz</span><span>(), </span><span>s</span><span>.</span><span>score</span><span>()));</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>        </span><span>// 2. 按班级分组</span></div></div><div><div><div>23</div></div><div><span>        </span><span>Map</span><span>&lt;</span><span>String</span><span>, </span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;&gt; </span><span>byClass</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>LinkedHashMap</span><span>&lt;&gt;();</span></div></div><div><div><div>24</div></div><div><span>        </span><span>for</span><span> (</span><span>Student</span><span><span> </span><span>s</span><span> </span></span><span>:</span><span> all)</span></div></div><div><div><div>25</div></div><div><span>            </span><span>byClass</span><span>.</span><span>computeIfAbsent</span><span>(</span><span>s</span><span>.</span><span>clazz</span><span>(), k </span><span>-&gt;</span><span> </span><span>new</span><span> </span><span>ArrayList</span><span>&lt;&gt;()).</span><span>add</span><span>(s);</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>        </span><span>byClass</span><span>.</span><span>forEach</span><span>((cls, list) </span><span>-&gt;</span><span> {</span></div></div><div><div><div>28</div></div><div><span>            </span><span>double</span><span><span> </span><span>avg</span><span> </span></span><span><span>=</span><span> </span></span><span>list</span><span>.</span><span>stream</span><span>().</span><span>mapToInt</span><span>(Student</span><span>::</span><span>score)</span></div></div><div><div><div>29</div></div><div><span><span>                             </span></span><span>.</span><span>average</span><span>().</span><span>orElse</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>30</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"%s: %d人 平均%.1f%n"</span><span>, cls, </span><span>list</span><span>.</span><span>size</span><span>(), avg);</span></div></div><div><div><div>31</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>        </span><span>// 3. 词频式统计分数段</span></div></div><div><div><div>34</div></div><div><span>        </span><span>Map</span><span>&lt;</span><span>String</span><span>, </span><span>Integer</span><span><span>&gt; </span><span>dist</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>TreeMap</span><span>&lt;&gt;();</span></div></div><div><div><div>35</div></div><div><span>        </span><span>for</span><span> (</span><span>Student</span><span><span> </span><span>s</span><span> </span></span><span>:</span><span> all) {</span></div></div><div><div><div>36</div></div><div><span>            </span><span>String</span><span><span> </span><span>band</span><span> </span></span><span><span>=</span><span> </span></span><span>s</span><span>.</span><span>score</span><span><span>() </span><span>&gt;=</span><span> </span></span><span>90</span><span> </span><span>?</span><span> </span><span>"90+"</span><span> </span><span>:</span><span> </span><span>s</span><span>.</span><span>score</span><span><span>() </span><span>&gt;=</span><span> </span></span><span>80</span><span> </span><span>?</span><span> </span><span>"80+"</span><span> </span><span>:</span></div></div><div><div><div>37</div></div><div><span>                          </span><span>s</span><span>.</span><span>score</span><span><span>() </span><span>&gt;=</span><span> </span></span><span>60</span><span> </span><span>?</span><span> </span><span>"60+"</span><span> </span><span>:</span><span> </span><span>"挂科"</span><span>;</span></div></div><div><div><div>38</div></div><div><span>            </span><span>dist</span><span>.</span><span>merge</span><span>(band, </span><span>1</span><span>, Integer</span><span>::</span><span>sum);</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"分数段: "</span><span><span> </span><span>+</span><span> dist);</span></span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>        </span><span>// 4. 挂科名单（stream 预告第十二篇）</span></div></div><div><div><div>43</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>String</span><span><span>&gt; </span><span>failed</span><span> </span></span><span><span>=</span><span> </span></span><span>all</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>44</div></div><div><span><span>                </span></span><span>.</span><span>filter</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span><span>() </span><span>&lt;</span><span> </span></span><span>60</span><span>)</span></div></div><div><div><div>45</div></div><div><span><span>                </span></span><span>.</span><span>map</span><span>(Student</span><span>::</span><span>name)</span></div></div><div><div><div>46</div></div><div><span><span>                </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>toList</span><span>());</span></div></div><div><div><div>47</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"挂科: "</span><span><span> </span><span>+</span><span> (</span></span><span>failed</span><span>.</span><span>isEmpty</span><span>() </span><span>?</span><span> </span><span>"无"</span><span> </span><span>:</span><span> failed));</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>七、容器选型决策表<a href="#七容器选型决策表"><span>#</span></a></h2>

<table><thead><tr><th>需求</th><th>选择</th></tr></thead><tbody><tr><td>动态列表（默认）</td><td><code>ArrayList</code></td></tr><tr><td>自动去重</td><td><code>HashSet</code> / 保序用 <code>LinkedHashSet</code></td></tr><tr><td>有序集合/排名</td><td><code>TreeSet</code></td></tr><tr><td>键值查找（默认）</td><td><code>HashMap</code></td></tr><tr><td>键值保插入序</td><td><code>LinkedHashMap</code></td></tr><tr><td>键有序遍历/范围查</td><td><code>TreeMap</code></td></tr><tr><td>一键多值</td><td><code>Map&lt;K, List&lt;V&gt;&gt;</code> + <code>computeIfAbsent</code></td></tr><tr><td>只读常量集合</td><td><code>List.of</code> / <code>Set.of</code> / <code>Map.of</code></td></tr></tbody></table></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>词频统计 Top3：按次数降序、同次数按字典序（entrySet 搬进 List 多级排序）</li>
<li>两个班级名单求：并集（去重）、交集、只在一班的人</li>
<li>用 <code>Map&lt;String, List&lt;String&gt;&gt;</code> 实现”分组通讯录”：录入若干 (姓名, 分组)，按组输出</li>
<li>模拟抽签：ArrayList 装 30 人，<code>Collections.shuffle</code> 后取前 5 名（TreeSet 记录已中签防重复）</li>
<li>给第四篇的 <code>merge(int[] a, int[] b)</code> 改用 <code>List&lt;Integer&gt;</code> 实现，对比两种容器的代码差异</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>List 有序可重复（ArrayList 默认）；Set 去重；Map 键值对</li>
<li>遍历中删除用 removeIf / 迭代器，防 fail-fast</li>
<li>自定义对象进 HashSet/HashMap：hashCode + equals 成对重写</li>
<li>merge/computeIfAbsent 是计数与分组的黄金搭档</li>
<li>Comparable 定天生序，Comparator 定策略序（comparing/reversed/thenComparing）</li>
<li>List.of 系列做不可变集合</li>
</ul><p><strong>下一篇</strong>：异常体系——try/catch 全解与自定义异常。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。merge 计数器 + computeIfAbsent 分组 = 集合实战双绝，务必掌握。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-09/</id>
      <title type="text">Java 入门教程（九）：异常处理</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-09/"/>
      <summary type="text">完整讲解 Java 异常体系：异常层级分类（受检/非受检）、try/catch/finally 执行规则、try-with-resources、throw 与 throws、自定义异常、异常设计最佳实践与常见误区。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>Java 的异常体系是所有语言里最”操心”的——编译器强制你处理部分异常。本篇讲透分类、语法、资源管理与设计原则。</p></section>
<section><h2>一、异常体系<a href="#一异常体系"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Throwable</span></div></div><div><div><div>2</div></div><div><span>├── Error                  ← 严重错误，程序管不了（OutOfMemoryError、StackOverflowError）</span></div></div><div><div><div>3</div></div><div><span>└── Exception</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>├── RuntimeException   ← 非受检异常（unchecked）：编译器不强制处理</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>│   ├── NullPointerException        空指针</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>│   ├── ArrayIndexOutOfBoundsException</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>│   ├── ArithmeticException        除零（整数）</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>│   ├── ClassCastException         强转失败</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>│   ├── NumberFormatException     parseInt("abc")</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>│   └── IllegalArgumentException   参数非法</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>└── 其他 Exception    ← 受检异常（checked）：编译器强制 try 或 throws</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>├── IOException</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>├── SQLException</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>└── FileNotFoundException</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>受检 vs 非受检</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 受检异常：不处理 → 编译不过</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>void</span><span> </span><span>readFile</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>FileReader</span><span> f </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>FileReader</span><span>(</span><span>"a.txt"</span><span><span>)</span><span>;</span><span>   </span></span><span>// ❌ 编译错误：未处理的 FileNotFoundException</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 非受检异常：处理与否自愿（通常是程序 bug 的信号）</span></div></div><div><div><div>7</div></div><div><span>public</span><span> </span><span>int</span><span> </span><span>div</span><span>(</span><span>int</span><span><span> a</span><span>,</span><span> </span></span><span>int</span><span> b) {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>return</span><span><span> a </span><span>/</span><span> b</span><span>;</span><span>      </span></span><span>// 可能 ArithmeticException，但不强制处理</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>二、try / catch / finally<a href="#二try--catch--finally"><span>#</span></a></h2><section><h3>基本结构<a href="#基本结构"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ExceptDemo</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>static</span><span> </span><span>int</span><span> </span><span>parse</span><span>(</span><span>String</span><span><span> </span><span>s</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> </span><span>Integer</span><span>.</span><span>parseInt</span><span>(s);       </span><span>// 可能 NumberFormatException</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>8</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>parse</span><span>(</span><span>"42"</span><span>));</span></div></div><div><div><div>9</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>parse</span><span>(</span><span>"abc"</span><span>));       </span><span>// 这里抛出</span></div></div><div><div><div>10</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"到不了这里"</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>NumberFormatException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"格式错误: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>Exception</span><span><span> </span><span>e</span><span>) {                       </span></span><span>// 兜底（子类在前父类在后！）</span></div></div><div><div><div>14</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"其他: "</span><span><span> </span><span>+</span><span> e);</span></span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>} </span><span>finally</span><span> {</span></div></div><div><div><div>16</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"finally 总会执行"</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>执行规则</strong>：</p><ul>
<li>try 中抛出位置之后的代码<strong>不执行</strong>，直接跳到匹配的 catch</li>
<li>catch 按<strong>顺序</strong>匹配，父类必须放后面（<code>catch (Exception)</code> 放第一会”吃掉”一切并导致后面不可达的编译错误）</li>
<li>finally <strong>无论如何都执行</strong>：正常结束、异常、甚至 try 里有 return</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>static</span><span> </span><span>int</span><span> </span><span>mystery</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>try</span><span> {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>} </span><span>finally</span><span> {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"finally 还是执行了！"</span><span><span>);</span><span>   </span></span><span>// 先打印，再 return 1</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>多异常合并捕获（Java 7+）<a href="#多异常合并捕获java-7"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>// ...</span></div></div><div><div><div>3</div></div><div><span>} </span><span>catch</span><span> (</span><span>IOException</span><span> | </span><span>SQLException</span><span><span> </span><span>e</span><span>) {      </span></span><span>// 竖线合并</span></div></div><div><div><div>4</div></div><div><span>    </span><span>log</span><span><span>(e)</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>获取异常信息<a href="#获取异常信息"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>catch</span><span> (</span><span>Exception</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>e</span><span>.</span><span>getMessage</span><span><span>();</span><span>           </span></span><span>// 简短描述</span></div></div><div><div><div>3</div></div><div><span>    </span><span>e</span><span>.</span><span>toString</span><span><span>();</span><span>             </span></span><span>// 类名 + 描述</span></div></div><div><div><div>4</div></div><div><span>    </span><span>e</span><span>.</span><span>printStackTrace</span><span><span>();</span><span>      </span></span><span>// 完整堆栈（调试用，别用于生产日志）</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、throw 与 throws<a href="#三throw-与-throws"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// throws：声明"本方法可能抛出这些异常，调用者负责"</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>setAge</span><span>(</span><span>int</span><span> age) throws IllegalArgumentException {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> (age </span><span>&lt;</span><span> </span></span><span>0</span><span><span> </span><span>||</span><span> age </span><span>&gt;</span><span> </span></span><span>150</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>        </span><span>// throw：真正抛出异常对象</span></div></div><div><div><div>5</div></div><div><span>        </span><span>throw</span><span> </span><span>new</span><span> </span><span>IllegalArgumentException</span><span>(</span><span>"年龄非法: "</span><span><span> </span><span>+</span><span> age)</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 自定义受检异常：继承 Exception</span></div></div><div><div><div>10</div></div><div><span>class</span><span><span> </span><span>InsufficientFundsException</span><span> </span></span><span>extends</span><span><span> </span><span>Exception</span><span> </span></span><span>{</span></div></div><div><div><div>11</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>double</span><span> shortfall</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>    </span><span>public</span><span> </span><span>InsufficientFundsException</span><span>(</span><span>double</span><span><span> </span><span>shortfall</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>super</span><span>(</span><span>String</span><span>.</span><span>format</span><span>(</span><span>"余额不足，还差 %.2f 元"</span><span>, shortfall));</span></div></div><div><div><div>15</div></div><div><span>        </span><span>this</span><span>.</span><span>shortfall</span><span><span> </span><span>=</span><span> shortfall;</span></span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>    </span><span>public</span><span> </span><span>double</span><span> </span><span>getShortfall</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> shortfall; }</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>Account</span><span> </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>    </span><span>private</span><span> </span><span>double</span><span> balance</span><span>;</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>    </span><span>// 受检异常：调用方必须 try-catch 或继续 throws（编译器盯着）</span></div></div><div><div><div>24</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>withdraw</span><span>(</span><span>double</span><span><span> </span><span>amount</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>InsufficientFundsException</span><span><span> </span><span>{</span></span></div></div><div><div><div>25</div></div><div><span>        </span><span>if</span><span><span> (amount </span><span>&gt;</span><span> balance)</span></span></div></div><div><div><div>26</div></div><div><span>            </span><span>throw</span><span> </span><span>new</span><span> </span><span>InsufficientFundsException</span><span><span>(amount </span><span>-</span><span> balance);</span></span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>balance </span><span>-=</span><span> amount;</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>// 调用方</span></div></div><div><div><div>32</div></div><div><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span>[] args) {</span></div></div><div><div><div>33</div></div><div><span>    </span><span>Account</span><span> acc </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Account</span><span><span>()</span><span>;</span></span></div></div><div><div><div>34</div></div><div><span>    </span><span>try</span><span> {</span></div></div><div><div><div>35</div></div><div><span>        </span><span>acc</span><span>.</span><span>withdraw</span><span>(</span><span>100</span><span>);</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>} </span><span>catch</span><span> (</span><span>InsufficientFundsException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>37</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>e</span><span>.</span><span>getMessage</span><span><span>());</span><span>           </span></span><span>// 余额不足，还差 100.00 元</span></div></div><div><div><div>38</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>e</span><span>.</span><span>getShortfall</span><span><span>());</span><span>          </span></span><span>// 100.0</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>受检/非受检的选型</strong>：调用方<strong>有能力恢复</strong>的（文件不存在→提示重选）→ 受检；<strong>程序 bug</strong>（空指针、参数错误）→ 非受检 RuntimeException，让它炸出来好修。</p></section>
<section><h2>四、try-with-resources：资源管理正解<a href="#四try-with-resources资源管理正解"><span>#</span></a></h2><section><h3>传统 finally 关资源的啰嗦<a href="#传统-finally-关资源的啰嗦"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 老写法：嵌套深、易漏</span></div></div><div><div><div>2</div></div><div><span>FileReader</span><span> fr </span><span><span>=</span><span> </span></span><span>null</span><span>;</span></div></div><div><div><div>3</div></div><div><span>try</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>fr </span><span>=</span><span> </span><span>new</span><span> </span><span>FileReader</span><span>(</span><span>"a.txt"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>int</span><span> c </span><span><span>=</span><span> </span></span><span>fr</span><span>.</span><span>read</span><span>();</span></div></div><div><div><div>6</div></div><div><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>e</span><span>.</span><span>printStackTrace</span><span>();</span></div></div><div><div><div>8</div></div><div><span>} </span><span>finally</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span><span> (fr </span><span>!=</span><span> </span></span><span>null</span><span>) {</span></div></div><div><div><div>10</div></div><div><span>        </span><span>try</span><span> { </span><span>fr</span><span>.</span><span>close</span><span><span>();</span><span> } </span></span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) { </span></span><span>e</span><span>.</span><span>printStackTrace</span><span><span>();</span><span> }</span></span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>try-with-resources（Java 7+，必用）<a href="#try-with-resourcesjava-7必用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 实现了 AutoCloseable 的资源放 try(...) 里，自动 close（哪怕抛异常）</span></div></div><div><div><div>2</div></div><div><span>try</span><span> (</span><span>FileReader</span><span> fr </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>FileReader</span><span>(</span><span>"a.txt"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>     </span><span>BufferedReader</span><span> br </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BufferedReader</span><span>(fr)) {       </span><span>// 多资源分号隔开</span></div></div><div><div><div>4</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>br</span><span>.</span><span>readLine</span><span>());</span></div></div><div><div><div>5</div></div><div><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"读取失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>// 离开 try 自动关，且后声明的先关（与声明顺序相反）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>军规</strong>：文件、数据库连接、网络流——一律 try-with-resources，告别手写 close。</p></section></section>
<section><h2>五、异常链与抑制<a href="#五异常链与抑制"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 异常链：底层异常包装成业务异常，保留根因</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>Config</span><span> </span><span>loadConfig</span><span>(</span><span>String</span><span> path) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>try</span><span> {</span></div></div><div><div><div>4</div></div><div><span>        </span><span>return</span><span> </span><span>parse</span><span>(</span><span>new</span><span> </span><span>String</span><span>(</span><span>java</span><span>.</span><span>nio</span><span>.</span><span>file</span><span>.</span><span>Files</span><span>.</span><span>readAllBytes</span><span>(</span></div></div><div><div><div>5</div></div><div><span>                </span><span>java</span><span>.</span><span>nio</span><span>.</span><span>file</span><span>.</span><span>Path</span><span>.</span><span>of</span><span><span>(path))</span><span>))</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>        </span><span>throw</span><span> </span><span>new</span><span> </span><span>ConfigException</span><span>(</span><span>"配置加载失败: "</span><span><span> </span><span>+</span><span> path</span><span>,</span><span> e)</span><span>;</span><span>   </span></span><span>// 传入原因</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>class</span><span><span> </span><span>ConfigException</span><span> </span></span><span>extends</span><span><span> </span><span>RuntimeException</span><span> </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>ConfigException</span><span>(</span><span>String</span><span><span> </span><span>msg</span><span>, </span></span><span>Throwable</span><span><span> </span><span>cause</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>super</span><span>(msg, cause);           </span><span>// cause 保留在堆栈里</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>// 打印时看到 Caused by: ... 链条，定位根因</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>六、最佳实践与常见误区<a href="#六最佳实践与常见误区"><span>#</span></a></h2><section><h3>✅ 该做的<a href="#-该做的"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 精确捕获，最小范围</span></div></div><div><div><div>2</div></div><div><span>try</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>int</span><span> n </span><span><span>=</span><span> </span></span><span>Integer</span><span>.</span><span>parseInt</span><span>(input);</span></div></div><div><div><div>4</div></div><div><span>} </span><span>catch</span><span> (</span><span>NumberFormatException</span><span><span> </span><span>e</span><span>) { </span></span><span>/* 只包可能出错的行 */</span><span> }</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 2. 捕获后要么处理、要么转换后抛出，别吞</span></div></div><div><div><div>7</div></div><div><span>try</span><span><span> { </span><span>...</span><span> }</span></span></div></div><div><div><div>8</div></div><div><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>log</span><span>.</span><span>error</span><span>(</span><span>"导入失败"</span><span>, e);</span></div></div><div><div><div>10</div></div><div><span>    </span><span>throw</span><span> </span><span>new</span><span> </span><span>ImportException</span><span>(</span><span>"数据导入失败"</span><span><span>,</span><span> e)</span><span>;</span><span>   </span></span><span>// 转成语义化异常上抛</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 3. finally 里别写 return（会覆盖 try 的返回值，极度迷惑）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>❌ 别做的<a href="#-别做的"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 空 catch 吞异常（出 bug 无迹可寻）</span></div></div><div><div><div>2</div></div><div><span>try</span><span> { </span><span>dangerous</span><span><span>()</span><span>;</span><span> } </span></span><span>catch</span><span> (</span><span>Exception</span><span><span> </span><span>e</span><span>) { }        </span></span><span>// 🔥 火灾隐患</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 2. 捕获 Error / 用异常控制正常流程</span></div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> </span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>try</span><span> { </span><span>list</span><span>.</span><span>get</span><span><span>(i);</span><span> } </span></span><span>catch</span><span> (</span><span>IndexOutOfBoundsException</span><span><span> </span><span>e</span><span>) { </span></span><span>break</span><span><span>;</span><span> }   </span></span><span>// ❌ 用循环条件</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 3. e.printStackTrace() 当日志（生产用日志框架 SLF4J）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 4. catch (Exception e) 一把梭（除非最外层兜底）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>早抛晚捕<a href="#早抛晚捕"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 参数校验尽早抛（fail fast）——Spring 的 Assert / Objects.requireNonNull</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>void</span><span> </span><span>transfer</span><span>(</span><span>Account</span><span><span> to</span><span>,</span><span> </span></span><span>double</span><span> amount) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>Objects</span><span>.</span><span>requireNonNull</span><span>(to, </span><span>"目标账户不能为空"</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> (amount </span><span>&lt;=</span><span> </span></span><span>0</span><span>) </span><span>throw</span><span> </span><span>new</span><span> </span><span>IllegalArgumentException</span><span>(</span><span>"金额必须为正"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>// ... 业务在可靠的输入上运行</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>七、实战：健壮的配置读取器<a href="#七实战健壮的配置读取器"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.io.IOException</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.io.InputStream</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>java.util.Properties</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>AppConfig</span><span> </span></span><span>{</span></div></div><div><div><div>6</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>Properties</span><span> props </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Properties</span><span><span>()</span><span>;</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>class</span><span><span> </span><span>ConfigException</span><span> </span></span><span>extends</span><span><span> </span><span>RuntimeException</span><span> </span></span><span>{</span></div></div><div><div><div>9</div></div><div><span>        </span><span>ConfigException</span><span>(</span><span>String</span><span><span> </span><span>msg</span><span>, </span></span><span>Throwable</span><span><span> </span><span>cause</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(msg, cause); }</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>AppConfig</span><span> </span><span>load</span><span>(</span><span>String</span><span><span> </span><span>filename</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>// try-with-resources + 异常链 + 语义化包装</span></div></div><div><div><div>14</div></div><div><span>        </span><span>try</span><span> (</span><span>InputStream</span><span><span> </span><span>in</span><span> </span></span><span><span>=</span><span> </span></span><span>AppConfig</span><span>.</span><span>class</span></div></div><div><div><div>15</div></div><div><span><span>                </span></span><span>.</span><span>getClassLoader</span><span>().</span><span>getResourceAsStream</span><span>(filename)) {</span></div></div><div><div><div>16</div></div><div><span>            </span><span>if</span><span><span> (in </span><span>==</span><span> </span></span><span>null</span><span>)</span></div></div><div><div><div>17</div></div><div><span>                </span><span>throw</span><span> </span><span>new</span><span> </span><span>ConfigException</span><span>(</span><span>"找不到配置文件: "</span><span><span> </span><span>+</span><span> filename, </span></span><span>null</span><span>);</span></div></div><div><div><div>18</div></div><div><span>            </span><span>AppConfig</span><span><span> </span><span>cfg</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>AppConfig</span><span>();</span></div></div><div><div><div>19</div></div><div><span>            </span><span>cfg</span><span>.</span><span>props</span><span>.</span><span>load</span><span>(in);</span></div></div><div><div><div>20</div></div><div><span>            </span><span>return</span><span> cfg;</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>22</div></div><div><span>            </span><span>throw</span><span> </span><span>new</span><span> </span><span>ConfigException</span><span>(</span><span>"读取 "</span><span><span> </span><span>+</span><span> filename </span><span>+</span><span> </span></span><span>" 失败"</span><span>, e);</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>    </span><span>public</span><span> </span><span>String</span><span> </span><span>get</span><span>(</span><span>String</span><span><span> </span><span>key</span><span>, </span></span><span>String</span><span><span> </span><span>def</span><span>)</span><span> </span><span>{           </span></span><span>// 安全读取</span></div></div><div><div><div>27</div></div><div><span>        </span><span>return</span><span> </span><span>props</span><span>.</span><span>getProperty</span><span>(key, def);</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>getInt</span><span>(</span><span>String</span><span><span> </span><span>key</span><span>, </span></span><span>int</span><span><span> </span><span>def</span><span>)</span><span> </span><span>{              </span></span><span>// 类型安全读取</span></div></div><div><div><div>31</div></div><div><span>        </span><span>String</span><span><span> </span><span>v</span><span> </span></span><span><span>=</span><span> </span></span><span>props</span><span>.</span><span>getProperty</span><span>(key);</span></div></div><div><div><div>32</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>33</div></div><div><span>            </span><span>return</span><span><span> v </span><span>==</span><span> </span></span><span>null</span><span> </span><span>?</span><span> def </span><span>:</span><span> </span><span>Integer</span><span>.</span><span>parseInt</span><span>(</span><span>v</span><span>.</span><span>trim</span><span>());</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>NumberFormatException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>35</div></div><div><span>            </span><span>System</span><span>.</span><span>err</span><span>.</span><span>printf</span><span>(</span><span>"配置 %s=%s 不是数字，用默认 %d%n"</span><span>, key, v, def);</span></div></div><div><div><div>36</div></div><div><span>            </span><span>return</span><span> def;</span></div></div><div><div><div>37</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>41</div></div><div><span>        </span><span>AppConfig</span><span><span> </span><span>cfg</span><span> </span></span><span><span>=</span><span> </span></span><span>load</span><span>(</span><span>"application.properties"</span><span>);</span></div></div><div><div><div>42</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"name = "</span><span><span> </span><span>+</span><span> </span></span><span>cfg</span><span>.</span><span>get</span><span>(</span><span>"app.name"</span><span>, </span><span>"未配置"</span><span>));</span></div></div><div><div><div>43</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"port = "</span><span><span> </span><span>+</span><span> </span></span><span>cfg</span><span>.</span><span>getInt</span><span>(</span><span>"app.port"</span><span>, </span><span>8080</span><span>));</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>45</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>这段代码展示了生产级套路</strong>：资源自动关、根因保留、语义化异常、带默认值的安全读取。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写方法 <code>divide(int a, int b)</code>：b 为 0 时抛自定义 <code>MathException</code>，main 里捕获处理</li>
<li>用 try-with-resources 读文本文件：文件不存在时给出友好提示（FileNotFoundException 分支）</li>
<li>实现 <code>safeParse(String[] args, int index)</code>：下标越界与格式错误都返回默认值 0 并打印警告</li>
<li>写三层调用 <code>main → service → dao</code>，dao 抛 IOException，service 包装成 ServiceException（带 cause），main 捕获打印完整链（观察 Caused by）</li>
<li>（概念）受检与非受检异常的区别？finally 一定会执行吗（System.exit 呢）？</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>Error 不救、受检异常必须处理、非受检是 bug 信号</li>
<li>catch 子类在前父类在后；finally 无条件执行</li>
<li>throw 抛对象、throws 声明甩锅；自定义异常继承 Exception（受检）或 RuntimeException（非受检）</li>
<li>资源管理一律 try-with-resources</li>
<li>异常链保留 Caused by；空 catch 与 printStackTrace 是大忌</li>
<li>早抛晚捕、精确捕获、fail fast</li>
</ul><p><strong>下一篇</strong>：文件 IO 与序列化——让数据落盘。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。“健壮配置读取器”是框架源码里的标准套路，读懂它。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-10/</id>
      <title type="text">Java 入门教程（十）：文件 IO 与 NIO</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-10/"/>
      <summary type="text">掌握 Java 文件读写全套路：File 与 Path、字节流与字符流、缓冲流、Files 工具类一行流（readString/write/lines/walk）、CSV 通讯录持久化实战、try-with-resources 综合运用。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>让数据活过进程的生命周期——<strong>读写文件</strong>。Java IO 类库庞大（几十个类），但日常 90% 的需求靠 <strong>Files 工具类 + 缓冲流</strong>就能解决。本篇按”现代优先”的路线讲。</p></section>
<section><h2>一、File 与 Path<a href="#一file-与-path"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.io.File</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.nio.file.</span><span>*</span><span><span>;</span><span>       </span></span><span>// NIO（New IO，Java 7+，推荐）</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 老牌 File</span></div></div><div><div><div>5</div></div><div><span>File</span><span> f </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>File</span><span>(</span><span>"data/demo.txt"</span><span><span>)</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>f</span><span>.</span><span>exists</span><span>();</span></div></div><div><div><div>7</div></div><div><span>f</span><span>.</span><span>isFile</span><span><span>();</span><span> </span></span><span>f</span><span>.</span><span>isDirectory</span><span>();</span></div></div><div><div><div>8</div></div><div><span>f</span><span>.</span><span>length</span><span><span>();</span><span>                  </span></span><span>// 字节数</span></div></div><div><div><div>9</div></div><div><span>f</span><span>.</span><span>delete</span><span>();</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// 现代 Path（推荐）</span></div></div><div><div><div>12</div></div><div><span>Path</span><span> p </span><span><span>=</span><span> </span></span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"data"</span><span>, </span><span>"demo.txt"</span><span><span>);</span><span>        </span></span><span>// 自动拼路径（跨平台分隔符）</span></div></div><div><div><div>13</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>p</span><span>.</span><span>getFileName</span><span><span>());</span><span>          </span></span><span>// demo.txt</span></div></div><div><div><div>14</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>p</span><span>.</span><span>toAbsolutePath</span><span><span>());</span><span>       </span></span><span>// /Users/xxx/项目/data/demo.txt</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>Files</span><span>.</span><span>exists</span><span>(p);</span></div></div><div><div><div>17</div></div><div><span>Files</span><span>.</span><span>size</span><span>(p);</span></div></div><div><div><div>18</div></div><div><span>Files</span><span>.</span><span>createDirectories</span><span>(</span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"a/b/c"</span><span><span>));</span><span>    </span></span><span>// 递归建目录</span></div></div><div><div><div>19</div></div><div><span>Files</span><span>.</span><span>delete</span><span><span>(p);</span><span>                              </span></span><span>// 删除（不存在抛异常）</span></div></div><div><div><div>20</div></div><div><span>Files</span><span>.</span><span>copy</span><span>(</span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"src"</span><span>), </span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"dst"</span><span>), </span><span>StandardCopyOption</span><span>.</span><span>REPLACE_EXISTING</span><span>);</span></div></div><div><div><div>21</div></div><div><span>Files</span><span>.</span><span>move</span><span>(src, dst);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>二、Files 工具类：一行流（日常首选）<a href="#二files-工具类一行流日常首选"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.nio.file.Files</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.nio.file.Path</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>java.io.IOException</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>Path</span><span> file </span><span><span>=</span><span> </span></span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"notes.txt"</span><span>);</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// —— 文本全家桶 ——</span></div></div><div><div><div>9</div></div><div><span>Files</span><span>.</span><span>writeString</span><span>(file, </span><span>"第一行</span><span>\n</span><span>"</span><span>, </span><span>StandardOpenOption</span><span>.</span><span>CREATE</span><span><span>);</span><span>   </span></span><span>// 覆盖写</span></div></div><div><div><div>10</div></div><div><span>Files</span><span>.</span><span>writeString</span><span>(file, </span><span>"追加的一行</span><span>\n</span><span>"</span><span>,</span></div></div><div><div><div>11</div></div><div><span>        </span><span>StandardOpenOption</span><span>.</span><span>CREATE</span><span>, </span><span>StandardOpenOption</span><span>.</span><span>APPEND</span><span><span>);</span><span>     </span></span><span>// 追加写</span></div></div><div><div><div>12</div></div><div><span>Files</span><span>.</span><span>writeString</span><span>(file, </span><span>"第三行</span><span>\n</span><span>"</span><span>, </span><span>StandardOpenOption</span><span>.</span><span>APPEND</span><span>);</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>String</span><span> all </span><span><span>=</span><span> </span></span><span>Files</span><span>.</span><span>readString</span><span><span>(file);</span><span>                  </span></span><span>// 一口气读完</span></div></div><div><div><div>15</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(all);</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> lines </span></span><span><span>=</span><span> </span></span><span>Files</span><span>.</span><span>readAllLines</span><span><span>(file);</span><span>        </span></span><span>// 按行读进 List</span></div></div><div><div><div>18</div></div><div><span>for</span><span> (</span><span>String</span><span> line </span><span>:</span><span> lines)</span></div></div><div><div><div>19</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"&gt; "</span><span><span> </span><span>+</span><span> line);</span></span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>// 流式逐行（大文件省内存）</span></div></div><div><div><div>22</div></div><div><span>try</span><span> (</span><span>var</span><span> stream </span><span><span>=</span><span> </span></span><span>Files</span><span>.</span><span>lines</span><span><span>(file)</span><span>) {</span></span></div></div><div><div><div>23</div></div><div><span>    </span><span>stream</span><span>.</span><span>filter</span><span>(l </span><span>-&gt;</span><span> </span><span>l</span><span>.</span><span>contains</span><span>(</span><span>"一"</span><span>))</span></div></div><div><div><div>24</div></div><div><span><span>          </span></span><span>.</span><span>forEach</span><span>(</span><span>System</span><span>.</span><span>out</span><span>::</span><span>println);</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>// —— 字节读（图片等二进制）——</span></div></div><div><div><div>28</div></div><div><span>byte</span><span>[] bytes </span><span><span>=</span><span> </span></span><span>Files</span><span>.</span><span>readAllBytes</span><span>(</span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"icon.png"</span><span>));</span></div></div><div><div><div>29</div></div><div><span>Files</span><span>.</span><span>write</span><span>(</span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"copy.png"</span><span>), bytes);</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>// —— 遍历目录树 ——</span></div></div><div><div><div>32</div></div><div><span>try</span><span> (</span><span>var</span><span> walk </span><span><span>=</span><span> </span></span><span>Files</span><span>.</span><span>walk</span><span>(</span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"."</span><span><span>))</span><span>) {           </span></span><span>// 递归所有子目录</span></div></div><div><div><div>33</div></div><div><span>    </span><span>walk</span><span>.</span><span>filter</span><span>(f </span><span>-&gt;</span><span> </span><span>f</span><span>.</span><span>toString</span><span>().</span><span>endsWith</span><span>(</span><span>".java"</span><span>))</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>.</span><span>limit</span><span>(</span><span>5</span><span>)</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>.</span><span>forEach</span><span>(</span><span>System</span><span>.</span><span>out</span><span>::</span><span>println);</span></div></div><div><div><div>36</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div></div><div>Tip</div></div><div><p>小文件（配置、日志、CSV）直接 Files 一行流；大文件用流式 <code>Files.lines</code>；两者都自动配 try-with-resources 最稳。</p></div></div></section>
<section><h2>三、经典 IO 流体系（读得懂老代码）<a href="#三经典-io-流体系读得懂老代码"><span>#</span></a></h2><section><h3>体系图<a href="#体系图"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>字节流（byte）              字符流（char，文本专用）</span></div></div><div><div><div>2</div></div><div><span>InputStream                 Reader</span></div></div><div><div><div>3</div></div><div><span>├── FileInputStream         ├── FileReader</span></div></div><div><div><div>4</div></div><div><span>└── BufferedInputStream ←── └── BufferedReader（缓冲，性能关键）</span></div></div><div><div><div>5</div></div><div><span>OutputStream                Writer</span></div></div><div><div><div>6</div></div><div><span>├── FileOutputStream        ├── FileWriter</span></div></div><div><div><div>7</div></div><div><span>└── BufferedOutputStream    └── BufferedWriter / PrintWriter</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>选择口诀</strong>：文本用字符流、二进制用字节流、<strong>永远套缓冲</strong>。</p></section><section><h3>字符读写模板<a href="#字符读写模板"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.io.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.Scanner</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>IoDemo</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>// —— 写：PrintWriter（有 println/print/printf，最顺手）——</span></div></div><div><div><div>7</div></div><div><span>        </span><span>try</span><span> (</span><span>PrintWriter</span><span><span> </span><span>out</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>PrintWriter</span><span>(</span></div></div><div><div><div>8</div></div><div><span>                </span><span>new</span><span> </span><span>BufferedWriter</span><span>(</span><span>new</span><span> </span><span>FileWriter</span><span>(</span><span>"diary.txt"</span><span>, </span><span>true</span><span>)))) {   </span><span>// true=追加</span></div></div><div><div><div>9</div></div><div><span>            </span><span>out</span><span>.</span><span>println</span><span>(</span><span>"2026-10-29 学完 Java IO"</span><span>);</span></div></div><div><div><div>10</div></div><div><span>            </span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"用时 %d 分钟%n"</span><span>, </span><span>45</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>            </span><span>System</span><span>.</span><span>err</span><span>.</span><span>println</span><span>(</span><span>"写失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>        </span><span>// —— 读 1：BufferedReader 逐行 ——</span></div></div><div><div><div>16</div></div><div><span>        </span><span>try</span><span> (</span><span>BufferedReader</span><span><span> </span><span>br</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>BufferedReader</span><span>(</span><span>new</span><span> </span><span>FileReader</span><span>(</span><span>"diary.txt"</span><span>))) {</span></div></div><div><div><div>17</div></div><div><span>            </span><span>String</span><span><span> </span><span>line</span></span><span>;</span></div></div><div><div><div>18</div></div><div><span>            </span><span>while</span><span><span> ((line </span><span>=</span><span> </span></span><span>br</span><span>.</span><span>readLine</span><span><span>()) </span><span>!=</span><span> </span></span><span>null</span><span>)     </span><span>// readLine 自动去换行符</span></div></div><div><div><div>19</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"| "</span><span><span> </span><span>+</span><span> line);</span></span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>21</div></div><div><span>            </span><span>e</span><span>.</span><span>printStackTrace</span><span>();</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>        </span><span>// —— 读 2：Scanner 读文件（nextInt 等 token 化）——</span></div></div><div><div><div>25</div></div><div><span>        </span><span>try</span><span> (</span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>new</span><span> </span><span>File</span><span>(</span><span>"data.txt"</span><span>))) {</span></div></div><div><div><div>26</div></div><div><span>            </span><span>while</span><span> (</span><span>sc</span><span>.</span><span>hasNextInt</span><span>())</span></div></div><div><div><div>27</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>sc</span><span>.</span><span>nextInt</span><span>());</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>FileNotFoundException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>29</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"文件不存在"</span><span>);</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>编码问题（中文乱码根源）<a href="#编码问题中文乱码根源"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// FileWriter 用系统默认编码（Windows 是 GBK！）——跨平台乱码之源</span></div></div><div><div><div>2</div></div><div><span>// ✅ 显式指定 UTF-8：</span></div></div><div><div><div>3</div></div><div><span>try</span><span> (</span><span>PrintWriter</span><span> out </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>PrintWriter</span><span>(</span><span>new</span><span> </span><span>BufferedWriter</span><span>(</span></div></div><div><div><div>4</div></div><div><span>        </span><span>new</span><span> </span><span>OutputStreamWriter</span><span>(</span></div></div><div><div><div>5</div></div><div><span>            </span><span>new</span><span> </span><span>FileOutputStream</span><span>(</span><span>"data.txt"</span><span><span>)</span><span>,</span><span> </span></span><span>java</span><span>.</span><span>nio</span><span>.</span><span>charset</span><span>.</span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>)))) {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>out</span><span>.</span><span>println</span><span>(</span><span>"中文内容"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// Files 系列默认就是 UTF-8（又一个用它的理由）</span></div></div><div><div><div>10</div></div><div><span>Files</span><span>.</span><span>readString</span><span>(file, </span><span>java</span><span>.</span><span>nio</span><span>.</span><span>charset</span><span>.</span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、对象序列化（了解）<a href="#四对象序列化了解"><span>#</span></a></h2><p>对象 ↔ 字节的相互转换，用于暂存或网络传输：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.io.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>class</span><span><span> </span><span>User</span><span> </span></span><span>implements</span><span><span> </span><span>Serializable</span><span> </span></span><span><span>{</span><span>          </span></span><span>// ① 实现标记接口</span></div></div><div><div><div>4</div></div><div><span>    </span><span>private</span><span> </span><span>static</span><span> </span><span>final</span><span> </span><span>long</span><span> serialVersionUID </span><span><span>=</span><span> </span></span><span>1L</span><span><span>;</span><span>   </span></span><span>// ② 版本号（改类不炸旧数据）</span></div></div><div><div><div>5</div></div><div><span>    </span><span>String</span><span> name</span><span>;</span></div></div><div><div><div>6</div></div><div><span>    </span><span>transient</span><span> </span><span>String</span><span> password</span><span><span>;</span><span>                 </span></span><span>// transient：敏感字段不序列化</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>User</span><span>(</span><span>String</span><span><span> </span><span>n</span><span>, </span></span><span>String</span><span><span> </span><span>p</span><span>)</span><span> </span><span>{ name </span><span>=</span><span> n; password </span><span>=</span><span> p; }</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>SerDemo</span><span> </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>Exception</span><span><span> </span><span>{</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>User</span><span><span> </span><span>u</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>User</span><span>(</span><span>"小明"</span><span>, </span><span>"123456"</span><span>);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>        </span><span>// 序列化</span></div></div><div><div><div>16</div></div><div><span>        </span><span>try</span><span> (</span><span>ObjectOutputStream</span><span><span> </span><span>oos</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ObjectOutputStream</span><span>(</span></div></div><div><div><div>17</div></div><div><span>                </span><span>new</span><span> </span><span>FileOutputStream</span><span>(</span><span>"user.dat"</span><span>))) {</span></div></div><div><div><div>18</div></div><div><span>            </span><span>oos</span><span>.</span><span>writeObject</span><span>(u);</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>        </span><span>// 反序列化</span></div></div><div><div><div>22</div></div><div><span>        </span><span>try</span><span> (</span><span>ObjectInputStream</span><span><span> </span><span>ois</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ObjectInputStream</span><span>(</span></div></div><div><div><div>23</div></div><div><span>                </span><span>new</span><span> </span><span>FileInputStream</span><span>(</span><span>"user.dat"</span><span>))) {</span></div></div><div><div><div>24</div></div><div><span>            </span><span>User</span><span><span> </span><span>back</span><span> </span></span><span><span>=</span><span> (User) </span></span><span>ois</span><span>.</span><span>readObject</span><span>();</span></div></div><div><div><div>25</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>back</span><span>.</span><span>name</span><span><span> </span><span>+</span><span> </span></span><span>" / "</span><span><span> </span><span>+</span><span> </span></span><span>back</span><span>.</span><span>password</span><span>);   </span><span>// 小明 / null</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>现代项目更多用 JSON（Jackson/Gson）替代原生序列化</strong>——可读、跨语言。原生序列化主要用于面试与理解机制。</p></section>
<section><h2>五、综合实战：CSV 通讯录（文件持久化）<a href="#五综合实战csv-通讯录文件持久化"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.io.IOException</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.nio.charset.StandardCharsets</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>java.nio.file.Files</span><span>;</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>java.nio.file.Path</span><span>;</span></div></div><div><div><div>5</div></div><div><span>import</span><span> </span><span>java.nio.file.StandardOpenOption</span><span>;</span></div></div><div><div><div>6</div></div><div><span>import</span><span> </span><span>java.util.ArrayList</span><span>;</span></div></div><div><div><div>7</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>8</div></div><div><span>import</span><span> </span><span>java.util.StringJoiner</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ContactBook</span><span> </span></span><span>{</span></div></div><div><div><div>11</div></div><div><span>    </span><span>record</span><span> </span><span>Contact</span><span>(</span><span>String</span><span><span> name</span><span>,</span><span> </span></span><span>String</span><span><span> phone</span><span>,</span><span> </span></span><span>String</span><span><span> group) </span><span>{</span></span></div></div><div><div><div>12</div></div><div><span>        </span><span>String</span><span> </span><span>toCsv</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>String</span><span>.</span><span>join</span><span>(</span><span>","</span><span><span>, name, phone, group); }</span><span>   </span></span><span>// 简单场景（值无逗号）</span></div></div><div><div><div>13</div></div><div><span>        </span><span>static</span><span> </span><span>Contact</span><span> </span><span>fromCsv</span><span>(</span><span>String</span><span><span> </span><span>line</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>14</div></div><div><span>            </span><span>String</span><span><span>[] </span><span>p</span><span> </span></span><span><span>=</span><span> </span></span><span>line</span><span>.</span><span>split</span><span>(</span><span>","</span><span><span>, </span><span>-</span></span><span>1</span><span>);        </span><span>// -1 保留空字段</span></div></div><div><div><div>15</div></div><div><span>            </span><span>return</span><span> </span><span>p</span><span>.</span><span>length</span><span><span> </span><span>==</span><span> </span></span><span>3</span><span> </span><span>?</span><span> </span><span>new</span><span> </span><span>Contact</span><span>(p[</span><span>0</span><span>], p[</span><span>1</span><span>], p[</span><span>2</span><span>]) </span><span>:</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>Path</span><span> file </span><span><span>=</span><span> </span></span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"contacts.csv"</span><span>);</span></div></div><div><div><div>20</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>List</span><span>&lt;</span><span>Contact</span><span><span>&gt;</span><span> data </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>    </span><span>public</span><span> </span><span>ContactBook</span><span><span>()</span><span> </span><span>{ </span></span><span>load</span><span>(); }</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>add</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>, </span></span><span>String</span><span><span> </span><span>phone</span><span>, </span></span><span>String</span><span><span> </span><span>group</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>25</div></div><div><span>        </span><span>data</span><span>.</span><span>add</span><span>(</span><span>new</span><span> </span><span>Contact</span><span>(name, phone, group));</span></div></div><div><div><div>26</div></div><div><span>        </span><span>save</span><span>();</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>    </span><span>public</span><span> </span><span>boolean</span><span> </span><span>delete</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>30</div></div><div><span>        </span><span>boolean</span><span><span> </span><span>removed</span><span> </span></span><span><span>=</span><span> </span></span><span>data</span><span>.</span><span>removeIf</span><span>(c </span><span>-&gt;</span><span> </span><span>c</span><span>.</span><span>name</span><span>().</span><span>equals</span><span>(name));</span></div></div><div><div><div>31</div></div><div><span>        </span><span>if</span><span> (removed) </span><span>save</span><span>();</span></div></div><div><div><div>32</div></div><div><span>        </span><span>return</span><span> removed;</span></div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>    </span><span>public</span><span> </span><span>List</span><span>&lt;</span><span>Contact</span><span><span>&gt;</span><span> </span></span><span>search</span><span>(</span><span>String</span><span><span> </span><span>kw</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>36</div></div><div><span>        </span><span>return</span><span> </span><span>data</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>37</div></div><div><span><span>                </span></span><span>.</span><span>filter</span><span>(c </span><span>-&gt;</span><span> </span><span>c</span><span>.</span><span>name</span><span>().</span><span>contains</span><span><span>(kw) </span><span>||</span><span> </span></span><span>c</span><span>.</span><span>phone</span><span>().</span><span>contains</span><span>(kw))</span></div></div><div><div><div>38</div></div><div><span><span>                </span></span><span>.</span><span>toList</span><span>();</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>listAll</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>42</div></div><div><span>        </span><span>StringJoiner</span><span><span> </span><span>sj</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>StringJoiner</span><span>(</span><span>"</span><span>\n</span><span>"</span><span>);</span></div></div><div><div><div>43</div></div><div><span>        </span><span>data</span><span>.</span><span>forEach</span><span>(c </span><span>-&gt;</span><span> </span><span>sj</span><span>.</span><span>add</span><span>(</span><span>String</span><span>.</span><span>format</span><span>(</span><span>"%-8s %-12s [%s]"</span><span>,</span></div></div><div><div><div>44</div></div><div><span>                </span><span>c</span><span>.</span><span>name</span><span>(), </span><span>c</span><span>.</span><span>phone</span><span>(), </span><span>c</span><span>.</span><span>group</span><span>())));</span></div></div><div><div><div>45</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(sj);</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>    </span><span>private</span><span> </span><span>void</span><span> </span><span>load</span><span><span>()</span><span> </span><span>{                          </span></span><span>// 启动时读</span></div></div><div><div><div>49</div></div><div><span>        </span><span>if</span><span><span> (</span><span>!</span></span><span>Files</span><span>.</span><span>exists</span><span>(file)) </span><span>return</span><span>;</span></div></div><div><div><div>50</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>51</div></div><div><span>            </span><span>for</span><span> (</span><span>String</span><span><span> </span><span>line</span><span> </span></span><span>:</span><span> </span><span>Files</span><span>.</span><span>readAllLines</span><span>(file, </span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>)) {</span></div></div><div><div><div>52</div></div><div><span>                </span><span>Contact</span><span><span> </span><span>c</span><span> </span></span><span><span>=</span><span> </span></span><span>Contact</span><span>.</span><span>fromCsv</span><span>(line);</span></div></div><div><div><div>53</div></div><div><span>                </span><span>if</span><span><span> (c </span><span>!=</span><span> </span></span><span>null</span><span>) </span><span>data</span><span>.</span><span>add</span><span>(c);</span></div></div><div><div><div>54</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>55</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>56</div></div><div><span>            </span><span>System</span><span>.</span><span>err</span><span>.</span><span>println</span><span>(</span><span>"读取失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>57</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>58</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span>    </span><span>private</span><span> </span><span>void</span><span> </span><span>save</span><span><span>()</span><span> </span><span>{                          </span></span><span>// 每次变更整写（小数据够用）</span></div></div><div><div><div>61</div></div><div><span>        </span><span>try</span><span> {</span></div></div><div><div><div>62</div></div><div><span>            </span><span>Files</span><span>.</span><span>write</span><span>(file,</span></div></div><div><div><div>63</div></div><div><span>                    </span><span>data</span><span>.</span><span>stream</span><span>().</span><span>map</span><span>(Contact</span><span>::</span><span>toCsv).</span><span>toList</span><span>(),</span></div></div><div><div><div>64</div></div><div><span>                    </span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>,</span></div></div><div><div><div>65</div></div><div><span>                    </span><span>StandardOpenOption</span><span>.</span><span>CREATE</span><span>,</span></div></div><div><div><div>66</div></div><div><span>                    </span><span>StandardOpenOption</span><span>.</span><span>TRUNCATE_EXISTING</span><span>);</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>68</div></div><div><span>            </span><span>System</span><span>.</span><span>err</span><span>.</span><span>println</span><span>(</span><span>"保存失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>69</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>70</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>71</div></div><div>
</div></div><div><div><div>72</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>73</div></div><div><span>        </span><span>ContactBook</span><span><span> </span><span>book</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ContactBook</span><span>();       </span><span>// 重启自动加载旧数据！</span></div></div><div><div><div>74</div></div><div>
</div></div><div><div><div>75</div></div><div><span>        </span><span>book</span><span>.</span><span>add</span><span>(</span><span>"小明"</span><span>, </span><span>"138xxxx"</span><span>, </span><span>"同学"</span><span>);</span></div></div><div><div><div>76</div></div><div><span>        </span><span>book</span><span>.</span><span>add</span><span>(</span><span>"小红"</span><span>, </span><span>"139xxxx"</span><span>, </span><span>"家人"</span><span>);</span></div></div><div><div><div>77</div></div><div><span>        </span><span>book</span><span>.</span><span>listAll</span><span>();</span></div></div><div><div><div>78</div></div><div>
</div></div><div><div><div>79</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"搜索'小': "</span><span><span> </span><span>+</span><span> </span></span><span>book</span><span>.</span><span>search</span><span>(</span><span>"小"</span><span>).</span><span>size</span><span><span>() </span><span>+</span><span> </span></span><span>" 条"</span><span>);</span></div></div><div><div><div>80</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"删除小红: "</span><span><span> </span><span>+</span><span> </span></span><span>book</span><span>.</span><span>delete</span><span>(</span><span>"小红"</span><span>));</span></div></div><div><div><div>81</div></div><div><span>        </span><span>book</span><span>.</span><span>listAll</span><span>();</span></div></div><div><div><div>82</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>83</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>技术点清单</strong>：record 数据类、Files 读写（UTF-8 显式）、stream 过滤、启动加载 + 变更即存——把它扩展成命令行交互就是毕业设计级作品。</p></section>
<section><h2>六、IO 选型决策<a href="#六io-选型决策"><span>#</span></a></h2>

<table><thead><tr><th>场景</th><th>方案</th></tr></thead><tbody><tr><td>小文本读写</td><td><code>Files.readString</code> / <code>writeString</code></td></tr><tr><td>逐行处理大文本</td><td><code>Files.lines</code>（流式）</td></tr><tr><td>按行写/格式化输出</td><td><code>PrintWriter</code> + 缓冲</td></tr><tr><td>读数字等 token</td><td><code>Scanner</code></td></tr><tr><td>二进制（图片）</td><td><code>Files.readAllBytes</code> / 字节流</td></tr><tr><td>遍历目录树</td><td><code>Files.walk</code></td></tr><tr><td>对象持久化</td><td>JSON 库（实战）/ Serializable（了解）</td></tr></tbody></table></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>统计文本文件：行数、字符数、最长的一行</li>
<li>合并多个日志文件为一个大文件（Files.readAllLines + write 追加）</li>
<li>找出某目录下所有大于 1MB 的文件并按大小排序输出（Files.walk + Files.size）</li>
<li>给通讯录加 <code>update</code> 命令与”导出为可读文本报表”功能</li>
<li>简易”日记本”：<code>write 内容</code> 追加带时间戳的一行，<code>list</code> 显示全部，<code>grep 关键词</code> 过滤</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>Path + Files 是现代首选：readString/writeString/readAllLines/lines/walk</li>
<li>流体系：文本字符流、二进制字节流、必套缓冲</li>
<li>编码显式 UTF-8，告别乱码；try-with-resources 管所有流</li>
<li>transient 排除敏感字段；实战持久化用 JSON 更香</li>
<li>启动加载 + 变更即存 = 最简持久化模型</li>
</ul><p><strong>下一篇</strong>：多线程与 Lambda——并发的世界与函数式语法糖。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。CSV 通讯录几乎串联了全系列知识，建议默写一遍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-11/</id>
      <title type="text">Java 入门教程（十一）：多线程与 Lambda</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-11/"/>
      <summary type="text">进入并发世界：Thread 创建两法与生命周期、synchronized 与原子类、ExecutorService 线程池、Lambda 与函数式接口、Optional 防空指针，附多线程下载统计实战。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>两个主题一次讲完：<strong>多线程</strong>（让程序同时干多件事）与 <strong>Lambda</strong>（函数式语法）。它们是 Java 8 的双主角，也是后端面试的必考区。目标：会建线程、懂同步、用线程池、熟练写 Lambda。</p></section>
<section><h2>一、线程基础<a href="#一线程基础"><span>#</span></a></h2><section><h3>为什么需要多线程<a href="#为什么需要多线程"><span>#</span></a></h3><p>单线程：下载文件时界面卡死（一件事阻塞一切）。多线程：下载归下载、界面归界面——<strong>并发</strong>提升响应与吞吐。</p></section><section><h3>创建线程两法<a href="#创建线程两法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 法1：继承 Thread</span></div></div><div><div><div>2</div></div><div><span>class</span><span><span> </span><span>Downloader</span><span> </span></span><span>extends</span><span><span> </span><span>Thread</span><span> </span></span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>String</span><span> file</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>Downloader</span><span>(</span><span>String</span><span><span> </span><span>file</span><span>)</span><span> </span><span>{ </span></span><span>this</span><span>.</span><span>file</span><span><span> </span><span>=</span><span> file; }</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>7</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>run</span><span><span>()</span><span> </span><span>{                     </span></span><span>// 线程要做的事</span></div></div><div><div><div>8</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"下载 "</span><span><span> </span><span>+</span><span> file </span><span>+</span><span> </span></span><span>" 开始"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>        </span><span>try</span><span> { </span><span>Thread</span><span>.</span><span>sleep</span><span>(</span><span>1000</span><span>); }         </span><span>// 模拟耗时</span></div></div><div><div><div>10</div></div><div><span>        </span><span>catch</span><span> (</span><span>InterruptedException</span><span><span> </span><span>e</span><span>) { </span></span><span>return</span><span>; }</span></div></div><div><div><div>11</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"下载 "</span><span><span> </span><span>+</span><span> file </span><span>+</span><span> </span></span><span>" 完成"</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>// 法2：实现 Runnable（推荐——不占用继承名额）</span></div></div><div><div><div>16</div></div><div><span>class</span><span><span> </span><span>Task</span><span> </span></span><span>implements</span><span><span> </span><span>Runnable</span><span> </span></span><span>{</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>18</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>run</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>19</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"任务运行在: "</span><span><span> </span><span>+</span><span> </span></span><span>Thread</span><span>.</span><span>currentThread</span><span>().</span><span>getName</span><span>());</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ThreadDemo</span><span> </span></span><span>{</span></div></div><div><div><div>24</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>InterruptedException</span><span><span> </span><span>{</span></span></div></div><div><div><div>25</div></div><div><span>        </span><span>Thread</span><span><span> </span><span>t1</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Downloader</span><span>(</span><span>"a.zip"</span><span>);</span></div></div><div><div><div>26</div></div><div><span>        </span><span>Thread</span><span><span> </span><span>t2</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Thread</span><span>(</span><span>new</span><span> </span><span>Task</span><span>(), </span><span>"工作线程-2"</span><span>);   </span><span>// 第二参命名</span></div></div><div><div><div>27</div></div><div><span>        </span><span>Thread</span><span><span> </span><span>t3</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Thread</span><span>(() </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"Lambda 更简洁"</span><span>),</span></div></div><div><div><div>28</div></div><div><span>                                </span><span>"工作线程-3"</span><span>);</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>        </span><span>t1</span><span>.</span><span>start</span><span>();      </span><span>// ⚠ 调 start() 不是 run()！run() 只是普通方法调用</span></div></div><div><div><div>31</div></div><div><span>        </span><span>t2</span><span>.</span><span>start</span><span>();</span></div></div><div><div><div>32</div></div><div><span>        </span><span>t3</span><span>.</span><span>start</span><span>();</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>        </span><span>t1</span><span>.</span><span>join</span><span>();       </span><span>// main 线程等 t1 干完再往下走</span></div></div><div><div><div>35</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"main 继续"</span><span>);</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div></div><div>Warning</div></div><div><p><code>start()</code> 启动新线程执行 run；直接调 <code>run()</code> 是在当前线程执行——没有新线程，这是新手第一大坑。</p></div></div></section><section><h3>常用方法<a href="#常用方法"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Thread</span><span> t </span><span><span>=</span><span> </span></span><span>Thread</span><span>.</span><span>currentThread</span><span><span>();</span><span>     </span></span><span>// 当前线程</span></div></div><div><div><div>2</div></div><div><span>t</span><span>.</span><span>getName</span><span>();</span></div></div><div><div><div>3</div></div><div><span>Thread</span><span>.</span><span>sleep</span><span>(</span><span>500</span><span><span>);</span><span>                     </span></span><span>// 当前线程睡 500ms（静态方法）</span></div></div><div><div><div>4</div></div><div><span>t</span><span>.</span><span>join</span><span><span>();</span><span>                              </span></span><span>// 等 t 结束</span></div></div><div><div><div>5</div></div><div><span>Thread</span><span>.</span><span>yield</span><span><span>();</span><span>                        </span></span><span>// 建议让出 CPU（了解）</span></div></div><div><div><div>6</div></div><div><span>t</span><span>.</span><span>setDaemon</span><span>(</span><span>true</span><span><span>);</span><span>                     </span></span><span>// 守护线程（主程序结束它陪葬）</span></div></div><div><div><div>7</div></div><div><span>t</span><span>.</span><span>setPriority</span><span>(</span><span>Thread</span><span>.</span><span>MAX_PRIORITY</span><span><span>);</span><span>    </span></span><span>// 优先级（仅建议性）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、线程安全与 synchronized<a href="#二线程安全与-synchronized"><span>#</span></a></h2><section><h3>竞态条件：多线程第一坑<a href="#竞态条件多线程第一坑"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Counter</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>private</span><span> </span><span>int</span><span> count </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>increment</span><span><span>()</span><span> </span><span>{ count++; }</span><span>      </span></span><span>// count++ 不是原子操作！</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>get</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> count; }</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 1000 个线程各加 1000 次 → 理论 100 万，实际常小于（丢失更新）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>count++</code> 实际是”读→改→写”三步，两线程交错执行就丢更新。</p></section><section><h3>synchronized：互斥锁<a href="#synchronized互斥锁"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>SafeCounter</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>private</span><span> </span><span>int</span><span> count </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>synchronized</span><span> </span><span>void</span><span> </span><span>increment</span><span><span>()</span><span> </span><span>{   </span></span><span>// 同一时刻只有一个线程能进入</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>count++;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>    </span><span>public</span><span> </span><span>synchronized</span><span> </span><span>int</span><span> </span><span>get</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> count; }</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// 同步块版（锁更小范围）</span></div></div><div><div><div>11</div></div><div><span>class</span><span><span> </span><span>Pair</span><span> </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>private</span><span> </span><span>int</span><span> a </span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>13</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>add</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>synchronized</span><span> (</span><span>this</span><span>) {                </span><span>// 锁住当前实例</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>a++;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>原子类：无锁方案（简单计数首选）<a href="#原子类无锁方案简单计数首选"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.concurrent.atomic.AtomicInteger</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>class</span><span><span> </span><span>AtomicCounter</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>private</span><span> </span><span>final</span><span> </span><span>AtomicInteger</span><span> count </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>AtomicInteger</span><span><span>()</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>increment</span><span><span>()</span><span> </span><span>{ </span></span><span>count</span><span>.</span><span>incrementAndGet</span><span><span>(); }</span><span>    </span></span><span>// CAS 实现，无锁高效</span></div></div><div><div><div>6</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>get</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>count</span><span>.</span><span>get</span><span>(); }</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>生产者-消费者（BlockingQueue，工程正解）<a href="#生产者-消费者blockingqueue工程正解"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.concurrent.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>ProducerConsumer</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>Exception</span><span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>BlockingQueue</span><span>&lt;</span><span>Integer</span><span><span>&gt; </span><span>queue</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>LinkedBlockingQueue</span><span>&lt;&gt;(</span><span>5</span><span>);  </span><span>// 容量5</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>        </span><span>// 生产者：往队列放（满了自动阻塞等待）</span></div></div><div><div><div>8</div></div><div><span>        </span><span>Thread</span><span><span> </span><span>producer</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Thread</span><span>(() </span><span>-&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span>            </span><span>try</span><span> {</span></div></div><div><div><div>10</div></div><div><span>                </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>i</span><span> </span></span><span><span>=</span><span> </span></span><span>1</span><span><span>; i </span><span>&lt;=</span><span> </span></span><span>10</span><span>; i++) {</span></div></div><div><div><div>11</div></div><div><span>                    </span><span>queue</span><span>.</span><span>put</span><span>(i);</span></div></div><div><div><div>12</div></div><div><span>                    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"生产 "</span><span><span> </span><span>+</span><span> i);</span></span></div></div><div><div><div>13</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>                </span><span>queue</span><span>.</span><span>put</span><span><span>(</span><span>-</span></span><span>1</span><span>);                       </span><span>// 结束信号</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>InterruptedException</span><span><span> </span><span>ignored</span><span>) {}</span></span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>        </span><span>// 消费者：从队列取（空了自动阻塞等待）</span></div></div><div><div><div>19</div></div><div><span>        </span><span>Thread</span><span><span> </span><span>consumer</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Thread</span><span>(() </span><span>-&gt;</span><span> {</span></div></div><div><div><div>20</div></div><div><span>            </span><span>try</span><span> {</span></div></div><div><div><div>21</div></div><div><span>                </span><span>int</span><span><span> </span><span>v</span></span><span>;</span></div></div><div><div><div>22</div></div><div><span>                </span><span>while</span><span><span> ((v </span><span>=</span><span> </span></span><span>queue</span><span>.</span><span>take</span><span><span>()) </span><span>!=</span><span> </span><span>-</span></span><span>1</span><span>)</span></div></div><div><div><div>23</div></div><div><span>                    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"  消费 "</span><span><span> </span><span>+</span><span> v);</span></span></div></div><div><div><div>24</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>InterruptedException</span><span><span> </span><span>ignored</span><span>) {}</span></span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>        </span><span>producer</span><span>.</span><span>start</span><span>();</span></div></div><div><div><div>28</div></div><div><span>        </span><span>consumer</span><span>.</span><span>start</span><span>();</span></div></div><div><div><div>29</div></div><div><span>        </span><span>producer</span><span>.</span><span>join</span><span>();</span></div></div><div><div><div>30</div></div><div><span>        </span><span>consumer</span><span>.</span><span>join</span><span>();</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>三、线程池：生产标配<a href="#三线程池生产标配"><span>#</span></a></h2><p>手动 new Thread 有创建销毁开销、无法控数量。<strong>线程池 = 线程复用 + 队列排队 + 限流</strong>：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.concurrent.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>PoolDemo</span><span> </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>Exception</span><span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div><span>        </span><span>// 固定 4 个工作线程的池</span></div></div><div><div><div>6</div></div><div><span>        </span><span>ExecutorService</span><span><span> </span><span>pool</span><span> </span></span><span><span>=</span><span> </span></span><span>Executors</span><span>.</span><span>newFixedThreadPool</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>        </span><span>// 提交 10 个任务（自动排队分发）</span></div></div><div><div><div>9</div></div><div><span>        </span><span>for</span><span> (</span><span>int</span><span><span> </span><span>i</span><span> </span></span><span><span>=</span><span> </span></span><span>1</span><span><span>; i </span><span>&lt;=</span><span> </span></span><span>10</span><span>; i++) {</span></div></div><div><div><div>10</div></div><div><span>            </span><span>final</span><span> </span><span>int</span><span><span> </span><span>taskId</span><span> </span></span><span><span>=</span><span> i;</span></span></div></div><div><div><div>11</div></div><div><span>            </span><span>pool</span><span>.</span><span>submit</span><span>(() </span><span>-&gt;</span><span> {                        </span><span>// submit 接收 Runnable/Callable</span></div></div><div><div><div>12</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"任务%d 由 %s 处理%n"</span><span>,</span></div></div><div><div><div>13</div></div><div><span><span>                        </span></span><span>taskId, </span><span>Thread</span><span>.</span><span>currentThread</span><span>().</span><span>getName</span><span>());</span></div></div><div><div><div>14</div></div><div><span>                </span><span>try</span><span> { </span><span>Thread</span><span>.</span><span>sleep</span><span>(</span><span>300</span><span>); }</span></div></div><div><div><div>15</div></div><div><span>                </span><span>catch</span><span> (</span><span>InterruptedException</span><span><span> </span><span>e</span><span>) { </span></span><span>Thread</span><span>.</span><span>currentThread</span><span>().</span><span>interrupt</span><span>(); }</span></div></div><div><div><div>16</div></div><div><span>                </span><span>return</span><span><span> taskId </span><span>*</span><span> taskId;                 </span></span><span>// Callable 可返回结果</span></div></div><div><div><div>17</div></div><div><span><span>            </span></span><span>});</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>        </span><span>// Callable + Future：拿异步结果</span></div></div><div><div><div>21</div></div><div><span>        </span><span>Future</span><span>&lt;</span><span>Integer</span><span><span>&gt; </span><span>future</span><span> </span></span><span><span>=</span><span> </span></span><span>pool</span><span>.</span><span>submit</span><span>(() </span><span>-&gt;</span><span> {</span></div></div><div><div><div>22</div></div><div><span>            </span><span>Thread</span><span>.</span><span>sleep</span><span>(</span><span>500</span><span>);</span></div></div><div><div><div>23</div></div><div><span>            </span><span>return</span><span> </span><span>42</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>25</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"等结果..."</span><span>);</span></div></div><div><div><div>26</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"结果 = "</span><span><span> </span><span>+</span><span> </span></span><span>future</span><span>.</span><span>get</span><span>());    </span><span>// 阻塞直到完成</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>        </span><span>pool</span><span>.</span><span>shutdown</span><span>();                                 </span><span>// 温和关闭（等任务做完）</span></div></div><div><div><div>29</div></div><div><span>        </span><span>// pool.awaitTermination(5, TimeUnit.SECONDS);</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>池的选型</strong>：</p>

<table><thead><tr><th>工厂方法</th><th>适用</th></tr></thead><tbody><tr><td><code>newFixedThreadPool(n)</code></td><td>负载稳定（默认首选）</td></tr><tr><td><code>newCachedThreadPool()</code></td><td>短时大量小任务</td></tr><tr><td><code>newSingleThreadExecutor()</code></td><td>任务需严格串行</td></tr></tbody></table><div><div><div></div><div>Tip</div></div><div><p>生产环境推荐 <code>new ThreadPoolExecutor(...)</code> 手动配七个参数（核心数/最大数/队列/拒绝策略），框架（Spring/Tomcat）内部全是定制池——入门先会 Executors，进阶再读源码。</p></div></div></section>
<section><h2>四、Lambda 与函数式接口<a href="#四lambda-与函数式接口"><span>#</span></a></h2><section><h3>从匿名内部类到 Lambda<a href="#从匿名内部类到-lambda"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 需求：按长度排序</span></div></div><div><div><div>2</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> list </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>ArrayList</span><span><span>&lt;&gt;</span><span>(</span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>"banana"</span><span>, </span><span>"apple"</span><span>, </span><span>"fig"</span><span><span>)</span><span>)</span><span>;</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 远古写法</span></div></div><div><div><div>5</div></div><div><span>list</span><span>.</span><span>sort</span><span>(</span><span>new</span><span> </span><span>Comparator</span><span>&lt;</span><span>String</span><span>&gt;() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>7</div></div><div><span>    </span><span>public</span><span> </span><span>int</span><span> </span><span>compare</span><span>(</span><span>String</span><span><span> </span><span>a</span><span>, </span></span><span>String</span><span><span> </span><span>b</span><span>)</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>a</span><span>.</span><span>length</span><span><span>() </span><span>-</span><span> </span></span><span>b</span><span>.</span><span>length</span><span>(); }</span></div></div><div><div><div>8</div></div><div><span>});</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// Lambda 写法</span></div></div><div><div><div>11</div></div><div><span>list</span><span>.</span><span>sort</span><span>((a, b) </span><span>-&gt;</span><span> </span><span>a</span><span>.</span><span>length</span><span><span>() </span><span>-</span><span> </span></span><span>b</span><span>.</span><span>length</span><span>());</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 方法引用：更极致的简洁</span></div></div><div><div><div>14</div></div><div><span>list</span><span>.</span><span>sort</span><span>(</span><span>Comparator</span><span>.</span><span>comparingInt</span><span>(String</span><span>::</span><span>length));</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Lambda 语法全解<a href="#lambda-语法全解"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// (参数) -&gt; 表达式 或 { 语句块 }</span></div></div><div><div><div>2</div></div><div><span>Runnable</span><span> r1 </span><span><span>=</span><span> () </span></span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"无参"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>Runnable</span><span> r2 </span><span><span>=</span><span> () </span></span><span>-&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"多行"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>    </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"要花括号"</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>}</span><span>;</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 单参可省括号（类型自动推断）</span></div></div><div><div><div>9</div></div><div><span>java</span><span>.</span><span>util</span><span>.</span><span>function</span><span>.</span><span>Function</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> len </span></span><span><span>=</span><span> s </span></span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>length</span><span>();</span></div></div><div><div><div>10</div></div><div><span>java</span><span>.</span><span>util</span><span>.</span><span>function</span><span>.</span><span>Function</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> len2 </span></span><span><span>=</span><span> String</span></span><span>::</span><span><span>length</span><span>;</span><span>   </span></span><span>// 方法引用</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>// 有返回值的</span></div></div><div><div><div>13</div></div><div><span>java</span><span>.</span><span>util</span><span>.</span><span>function</span><span>.</span><span>BinaryOperator</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> add </span></span><span><span>=</span><span> (a</span><span>,</span><span> b) </span></span><span>-&gt;</span><span><span> a </span><span>+</span><span> b</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>四大函数式接口（java.util.function）<a href="#四大函数式接口javautilfunction"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// Function&lt;T,R&gt;：T → R（转换）</span></div></div><div><div><div>2</div></div><div><span>Function</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> parse </span></span><span><span>=</span><span> Integer</span></span><span>::</span><span><span>parseInt</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>parse</span><span>.</span><span>apply</span><span>(</span><span>"42"</span><span>));</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// Predicate&lt;T&gt;：T → boolean（判断）</span></div></div><div><div><div>6</div></div><div><span>Predicate</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> isEmpty </span></span><span><span>=</span><span> String</span></span><span>::</span><span><span>isEmpty</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>isEmpty</span><span>.</span><span>test</span><span>(</span><span>""</span><span><span>));</span><span>        </span></span><span>// true</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// Consumer&lt;T&gt;：T → void（消费）</span></div></div><div><div><div>10</div></div><div><span>Consumer</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> printer </span></span><span><span>=</span><span> s </span></span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"⚡ "</span><span><span> </span><span>+</span><span> s);</span></span></div></div><div><div><div>11</div></div><div><span>printer</span><span>.</span><span>accept</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// Supplier&lt;T&gt;：() → T（生产/惰性）</span></div></div><div><div><div>14</div></div><div><span>Supplier</span><span>&lt;</span><span>Double</span><span><span>&gt;</span><span> random </span></span><span><span>=</span><span> Math</span></span><span>::</span><span><span>random</span><span>;</span></span></div></div><div><div><div>15</div></div><div><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>random</span><span>.</span><span>get</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>Lambda 能出现在任何”函数式接口”（只有一个抽象方法的接口）的位置</strong>——Runnable、Comparator、以及上面四大金刚。</p></section><section><h3>方法引用四式<a href="#方法引用四式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span>::</span><span>length            </span><span>// 对象方法：x -&gt; x.length()</span></div></div><div><div><div>2</div></div><div><span>System</span><span>.</span><span>out</span><span>::</span><span>println       </span><span>// 特定对象方法：x -&gt; System.out.println(x)</span></div></div><div><div><div>3</div></div><div><span>Integer</span><span>::</span><span>parseInt         </span><span>// 静态方法：s -&gt; Integer.parseInt(s)</span></div></div><div><div><div>4</div></div><div><span>ArrayList</span><span>::new</span><span>            </span><span>// 构造器：() -&gt; new ArrayList&lt;&gt;()</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、Optional：告别 NPE<a href="#五optional告别-npe"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.Optional</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// 包装可能为 null 的返回值</span></div></div><div><div><div>4</div></div><div><span>Optional</span><span><span>&lt;</span><span>String</span><span>&gt;</span><span> </span></span><span>findUser</span><span>(</span><span>int</span><span> id) {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span><span> id </span><span>==</span><span> </span></span><span>1</span><span> </span><span>?</span><span> </span><span>Optional</span><span>.</span><span>of</span><span>(</span><span>"小明"</span><span><span>)</span><span> </span></span><span>:</span><span> </span><span>Optional</span><span>.</span><span>empty</span><span>();</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// 使用方（再也不写 if (x != null)）</span></div></div><div><div><div>9</div></div><div><span>findUser</span><span>(</span><span>1</span><span><span>)</span><span>.</span></span><span>ifPresent</span><span>(name </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"找到 "</span><span><span> </span><span>+</span><span> name));</span></span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>String</span><span> name </span><span><span>=</span><span> </span></span><span>findUser</span><span>(</span><span>2</span><span><span>)</span><span>.</span></span><span>orElse</span><span>(</span><span>"游客"</span><span><span>);</span><span>                 </span></span><span>// 默认值</span></div></div><div><div><div>12</div></div><div><span>String</span><span> n2 </span><span><span>=</span><span> </span></span><span>findUser</span><span>(</span><span>2</span><span><span>)</span><span>.</span></span><span>orElseGet</span><span>(() </span><span>-&gt;</span><span> </span><span>"懒加载默认"</span><span><span>);</span><span>     </span></span><span>// 惰性默认</span></div></div><div><div><div>13</div></div><div><span>String</span><span> n3 </span><span><span>=</span><span> </span></span><span>findUser</span><span>(</span><span>1</span><span><span>)</span><span>.</span></span><span>orElseThrow</span><span>(</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>() </span><span>-&gt;</span><span> </span><span>new</span><span> </span><span>RuntimeException</span><span>(</span><span>"用户不存在"</span><span><span>));</span><span>          </span></span><span>// 强制要求</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>六、实战：并发下载统计<a href="#六实战并发下载统计"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.concurrent.</span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.concurrent.atomic.AtomicLong</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>DownloadSimulator</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>Exception</span><span><span> </span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>String</span><span><span>[] </span><span>files</span><span> </span></span><span><span>=</span><span> {</span></span><span>"a.zip"</span><span>, </span><span>"b.zip"</span><span>, </span><span>"c.zip"</span><span>, </span><span>"d.zip"</span><span>, </span><span>"e.zip"</span><span>};</span></div></div><div><div><div>7</div></div><div><span>        </span><span>AtomicLong</span><span><span> </span><span>totalBytes</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>AtomicLong</span><span>();        </span><span>// 原子累计</span></div></div><div><div><div>8</div></div><div><span>        </span><span>ExecutorService</span><span><span> </span><span>pool</span><span> </span></span><span><span>=</span><span> </span></span><span>Executors</span><span>.</span><span>newFixedThreadPool</span><span>(</span><span>3</span><span>);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>        </span><span>var</span><span><span> </span><span>futures</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>java</span><span>.</span><span>util</span><span>.</span><span>ArrayList</span><span>&lt;</span><span>Future</span><span>&lt;</span><span>Long</span><span>&gt;&gt;();</span></div></div><div><div><div>11</div></div><div><span>        </span><span>long</span><span><span> </span><span>start</span><span> </span></span><span><span>=</span><span> </span></span><span>System</span><span>.</span><span>currentTimeMillis</span><span>();</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>        </span><span>for</span><span> (</span><span>String</span><span><span> </span><span>f</span><span> </span></span><span>:</span><span> files) {</span></div></div><div><div><div>14</div></div><div><span>            </span><span>futures</span><span>.</span><span>add</span><span>(</span><span>pool</span><span>.</span><span>submit</span><span>(() </span><span>-&gt;</span><span> {              </span><span>// Callable 返回本文件字节数</span></div></div><div><div><div>15</div></div><div><span>                </span><span>Thread</span><span>.</span><span>sleep</span><span>(</span><span>500</span><span>);                       </span><span>// 模拟下载</span></div></div><div><div><div>16</div></div><div><span>                </span><span>long</span><span><span> </span><span>size</span><span> </span></span><span><span>=</span><span> (</span></span><span>long</span><span>) (</span><span>Math</span><span>.</span><span>random</span><span><span>() </span><span>*</span><span> </span></span><span>1_000_000</span><span>);</span></div></div><div><div><div>17</div></div><div><span>                </span><span>totalBytes</span><span>.</span><span>addAndGet</span><span>(size);</span></div></div><div><div><div>18</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"  [%s] %s 完成: %,d B%n"</span><span>,</span></div></div><div><div><div>19</div></div><div><span>                        </span><span>Thread</span><span>.</span><span>currentThread</span><span>().</span><span>getName</span><span>(), f, size);</span></div></div><div><div><div>20</div></div><div><span>                </span><span>return</span><span> size;</span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>}));</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>        </span><span>long</span><span><span> </span><span>sum</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>25</div></div><div><span>        </span><span>for</span><span> (</span><span>Future</span><span>&lt;</span><span>Long</span><span><span>&gt; </span><span>fu</span><span> </span></span><span>:</span><span><span> futures) sum </span><span>+=</span><span> </span></span><span>fu</span><span>.</span><span>get</span><span>(); </span><span>// 收齐结果</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>        </span><span>pool</span><span>.</span><span>shutdown</span><span>();</span></div></div><div><div><div>28</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"全部完成：%d 文件，共 %,d 字节，并发耗时 %d ms%n"</span><span>,</span></div></div><div><div><div>29</div></div><div><span>                </span><span>files</span><span>.</span><span>length</span><span>, sum,</span></div></div><div><div><div>30</div></div><div><span>                </span><span>System</span><span>.</span><span>currentTimeMillis</span><span><span>() </span><span>-</span><span> start);     </span></span><span>// 约 1 秒（串行要 2.5 秒）</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>创建 3 个线程分别打印 1~20，观察输出交错；用 <code>join</code> 让它们严格顺序执行</li>
<li>用 AtomicInteger 写”10 线程各加 10 万次”验证总数正确；改成普通 int 对比丢失</li>
<li>线程池提交 20 个计算任务（平方），用 <code>Future</code> 收集结果求和</li>
<li>用 <code>Function</code> 链式组合：<code>andThen</code> 实现”字符串 → 长度 → 平方”</li>
<li>用 Optional 重写”根据 id 查学生成绩”：找不到返回默认 0 并打印提示</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>Thread 两种创建法；start() 启动、join() 等待；sleep 静态方法</li>
<li>count++ 非原子；synchronized 互斥、AtomicInteger 无锁计数</li>
<li>BlockingQueue 天然解决生产者消费者</li>
<li>线程池三工厂 + submit/Future 收结果；生产用 ThreadPoolExecutor 定制</li>
<li>Lambda 只认函数式接口；四大金刚 Function/Predicate/Consumer/Supplier</li>
<li>方法引用四式；Optional 优雅防空</li>
</ul><p><strong>下一篇</strong>：Stream API 与综合实战——系列的收官之战。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。“并发耗时 vs 串行耗时”的对比实验请亲手跑，体感最深刻。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/java-tutorial-12/</id>
      <title type="text">Java 入门教程（十二）：Stream API 与综合实战</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/java-tutorial-12/"/>
      <summary type="text">系列收官：Stream 流式处理全解（创建/中间/终端操作、Collectors 收集、分组统计）、Optional 链式防 NPE、综合实战学生管理系统（控制台 CRUD + 集合 + 文件 + 异常 + 多线程），附全系列总结。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>双主题收官：<strong>Stream API</strong>（Java 8 最优雅的数据处理武器）+ <strong>综合实战</strong>（用全系列知识写一个学生管理系统）。</p></section>
<section><h2>一、Stream API<a href="#一stream-api"><span>#</span></a></h2><section><h3>是什么<a href="#是什么"><span>#</span></a></h3><p>Stream 是<strong>数据流水线</strong>：<code>数据源 → 中间操作（惰性）→ 终端操作（触发）</code>。它不存数据、不改源，只声明”怎么处理”：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>java.util.List</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.util.stream.Collectors</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> names </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>"小明"</span><span>, </span><span>"小红"</span><span>, </span><span>"小刚"</span><span>, </span><span>"小美"</span><span>, </span><span>"小强"</span><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> result </span></span><span><span>=</span><span> </span></span><span>names</span><span>.</span><span>stream</span><span><span>()</span><span>            </span></span><span>// ① 建流</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>.</span><span>filter</span><span>(n </span><span>-&gt;</span><span> </span><span>n</span><span>.</span><span>startsWith</span><span>(</span><span>"小"</span><span><span>))</span><span>          </span></span><span>// ② 中间操作：过滤（还没执行！）</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>.</span><span>map</span><span>(String</span><span>::</span><span><span>length)</span><span>                      </span></span><span>// ③ 中间操作：变换</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>toList</span><span><span>());</span><span>            </span></span><span>// ④ 终端操作：触发整条流水线</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>创建流的三种方式<a href="#创建流的三种方式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 集合 → stream()</span></div></div><div><div><div>2</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> list </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>3</div></div><div><span>list</span><span>.</span><span>stream</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 数组 → Arrays.stream</span></div></div><div><div><div>6</div></div><div><span>int</span><span>[] arr </span><span><span>=</span><span> {</span></span><span>1</span><span><span>,</span><span> </span></span><span>2</span><span><span>,</span><span> </span></span><span>3</span><span><span>}</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>Arrays</span><span>.</span><span>stream</span><span>(arr).</span><span>sum</span><span>();</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 静态工厂 → Stream.of / generate / iterate</span></div></div><div><div><div>10</div></div><div><span>Stream</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> s1 </span></span><span><span>=</span><span> </span></span><span>Stream</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>11</div></div><div><span>Stream</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> s2 </span></span><span><span>=</span><span> </span></span><span>Stream</span><span>.</span><span>iterate</span><span>(</span><span>1</span><span>, n </span><span>-&gt;</span><span><span> n </span><span>*</span><span> </span></span><span>2</span><span>).</span><span>limit</span><span>(</span><span>10</span><span><span>);</span><span>    </span></span><span>// 1,2,4,8...1024</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>中间操作全家桶<a href="#中间操作全家桶"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> nums </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>5</span><span>, </span><span>3</span><span>, </span><span>8</span><span>, </span><span>1</span><span>, </span><span>3</span><span>, </span><span>9</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// filter：过滤</span></div></div><div><div><div>4</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>filter</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&gt;</span><span> </span></span><span>3</span><span>).</span><span>forEach</span><span>(</span><span>System</span><span>.</span><span>out</span><span>::</span><span><span>println);</span><span>   </span></span><span>// 5 8 9</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// map：一对一变换</span></div></div><div><div><div>7</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>map</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>*</span><span> n).</span></span><span>forEach</span><span>(</span><span>System</span><span>.</span><span>out</span><span>::</span><span><span>println);</span><span>      </span></span><span>// 25 9 64 ...</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// distinct / sorted / limit / skip</span></div></div><div><div><div>10</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>distinct</span><span>().</span><span>sorted</span><span>().</span><span>limit</span><span>(</span><span>3</span><span>).</span><span>toList</span><span><span>();</span><span>             </span></span><span>// [1, 2, 3]</span></div></div><div><div><div>11</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>sorted</span><span>(</span><span>Comparator</span><span>.</span><span>reverseOrder</span><span>()).</span><span>skip</span><span>(</span><span>1</span><span>).</span><span>toList</span><span><span>();</span><span> </span></span><span>// [8,5,3,3,2]</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// flatMap：一对多展开（流中流拍扁）</span></div></div><div><div><div>14</div></div><div><span>List</span><span>&lt;</span><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;&gt;</span><span> nested </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>List</span><span>.</span><span>of</span><span>(</span><span>1</span><span>, </span><span>2</span><span>), </span><span>List</span><span>.</span><span>of</span><span>(</span><span>3</span><span>, </span><span>4</span><span>));</span></div></div><div><div><div>15</div></div><div><span>nested</span><span>.</span><span>stream</span><span>().</span><span>flatMap</span><span>(List</span><span>::</span><span>stream).</span><span>toList</span><span><span>();</span><span>                   </span></span><span>// [1,2,3,4]</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>// peek：偷看（调试利器）</span></div></div><div><div><div>18</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>peek</span><span>(n </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"处理中: "</span><span><span> </span><span>+</span><span> n))</span></span></div></div><div><div><div>19</div></div><div><span><span>     </span></span><span>.</span><span>map</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>+</span><span> </span></span><span>1</span><span>).</span><span>toList</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>终端操作全家桶<a href="#终端操作全家桶"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>List</span><span>&lt;</span><span>Integer</span><span><span>&gt;</span><span> nums </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span><span>5</span><span>, </span><span>3</span><span>, </span><span>8</span><span>, </span><span>1</span><span>, </span><span>9</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// —— 归约计算 ——</span></div></div><div><div><div>4</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>count</span><span><span>();</span><span>                          </span></span><span>// 5</span></div></div><div><div><div>5</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>mapToInt</span><span>(Integer</span><span>::</span><span>intValue).</span><span>sum</span><span>();</span><span>// 26（先转 IntStream 性能更好）</span></div></div><div><div><div>6</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>max</span><span>(Integer</span><span>::</span><span><span>compareTo);</span><span>          </span></span><span>// Optional[9]</span></div></div><div><div><div>7</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>min</span><span>(Integer</span><span>::</span><span><span>compareTo);</span><span>          </span></span><span>// Optional[1]</span></div></div><div><div><div>8</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>filter</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&gt;</span><span> </span></span><span>3</span><span>).</span><span>findFirst</span><span><span>();</span><span>   </span></span><span>// Optional[5]</span></div></div><div><div><div>9</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>filter</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&gt;</span><span> </span></span><span>3</span><span>).</span><span>findAny</span><span>();</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>// —— 匹配判断 ——</span></div></div><div><div><div>12</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>allMatch</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&gt;</span><span> </span></span><span>0</span><span><span>);</span><span>             </span></span><span>// true（全部满足）</span></div></div><div><div><div>13</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>anyMatch</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&gt;</span><span> </span></span><span>8</span><span><span>);</span><span>             </span></span><span>// true（任一满足）</span></div></div><div><div><div>14</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>noneMatch</span><span>(n </span><span>-&gt;</span><span><span> n </span><span>&lt;</span><span> </span></span><span>0</span><span><span>);</span><span>            </span></span><span>// true（都不满足）</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>// —— 遍历 ——</span></div></div><div><div><div>17</div></div><div><span>nums</span><span>.</span><span>stream</span><span>().</span><span>forEach</span><span>(</span><span>System</span><span>.</span><span>out</span><span>::</span><span>println);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>Collectors：收集器（最强大）<a href="#collectors收集器最强大"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;</span><span> st </span></span><span><span>=</span><span> </span></span><span>List</span><span>.</span><span>of</span><span>(</span></div></div><div><div><div>2</div></div><div><span>    </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小明"</span><span>, </span><span>"一班"</span><span>, </span><span>90</span><span>),</span></div></div><div><div><div>3</div></div><div><span>    </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小红"</span><span>, </span><span>"二班"</span><span>, </span><span>85</span><span>),</span></div></div><div><div><div>4</div></div><div><span>    </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小刚"</span><span>, </span><span>"一班"</span><span>, </span><span>92</span><span>),</span></div></div><div><div><div>5</div></div><div><span>    </span><span>new</span><span> </span><span>Student</span><span>(</span><span>"小美"</span><span>, </span><span>"二班"</span><span>, </span><span>78</span><span>));</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// toList / toSet</span></div></div><div><div><div>8</div></div><div><span>List</span><span>&lt;</span><span>String</span><span><span>&gt;</span><span> names </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>().</span><span>map</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>).</span><span>toList</span><span><span>();</span><span>   </span></span><span>// Java 16+ 直接 toList</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>// joining：字符串拼接</span></div></div><div><div><div>11</div></div><div><span>String</span><span> all </span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>().</span><span>map</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>)</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>joining</span><span>(</span><span>", "</span><span>, </span><span>"["</span><span>, </span><span>"]"</span><span><span>));</span><span>         </span></span><span>// [小明, 小红, 小刚, 小美]</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// groupingBy：分组（Map&lt;String, List&lt;Student&gt;&gt;）</span></div></div><div><div><div>15</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;&gt;</span><span> byClass </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>groupingBy</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>clazz</span><span>));</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>// 分组 + 下游统计</span></div></div><div><div><div>19</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Long</span><span><span>&gt;</span><span> countByClass </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>groupingBy</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>clazz</span><span>, </span><span>Collectors</span><span>.</span><span>counting</span><span>()));</span></div></div><div><div><div>21</div></div><div><span>// {一班=2, 二班=2}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Double</span><span><span>&gt;</span><span> avgByClass </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>groupingBy</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>clazz</span><span>,</span></div></div><div><div><div>25</div></div><div><span>                 </span><span>Collectors</span><span>.</span><span>averagingDouble</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span>)));</span></div></div><div><div><div>26</div></div><div><span>// {一班=91.0, 二班=81.5}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Optional</span><span>&lt;</span><span>Student</span><span><span>&gt;&gt;</span><span> topByClass </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>groupingBy</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>clazz</span><span>,</span></div></div><div><div><div>30</div></div><div><span>                 </span><span>Collectors</span><span>.</span><span>maxBy</span><span>(</span><span>Comparator</span><span>.</span><span>comparing</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span>))));</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>// partitioningBy：按布尔分两组</span></div></div><div><div><div>33</div></div><div><span>Map</span><span>&lt;</span><span>Boolean</span><span><span>,</span><span> </span></span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;&gt;</span><span> passFail </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>partitioningBy</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span><span> </span><span>&gt;=</span><span> </span></span><span>60</span><span>));</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>// toMap：收集成 Map</span></div></div><div><div><div>37</div></div><div><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Integer</span><span><span>&gt;</span><span> scoreMap </span></span><span><span>=</span><span> </span></span><span>st</span><span>.</span><span>stream</span><span>()</span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>toMap</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>, s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>score</span><span>,</span></div></div><div><div><div>39</div></div><div><span><span>                </span></span><span>(a, b) </span><span>-&gt;</span><span><span> b));</span><span>                 </span></span><span>// 第3参处理键冲突</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>并行流一行提速<a href="#并行流一行提速"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>long</span><span> sum </span><span><span>=</span><span> </span></span><span>java</span><span>.</span><span>util</span><span>.</span><span>stream</span><span>.</span><span>IntStream</span><span>.</span><span>rangeClosed</span><span>(</span><span>1</span><span>, </span><span>100_000_000</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>        </span></span><span>.</span><span>parallel</span><span><span>()</span><span>                             </span></span><span>// 一行变多核并行</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>.</span><span>sum</span><span>();</span></div></div><div><div><div>4</div></div><div><span>// 适合：数据量大 + 元素计算重；小数据反而更慢（线程切换开销）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、综合实战：学生管理系统<a href="#二综合实战学生管理系统"><span>#</span></a></h2><p>全系列知识总集成：OOP + 集合 + 异常 + IO + 多线程。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// ===== StudentSystem.java 完整可编译 =====</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>java.io.IOException</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>java.nio.charset.StandardCharsets</span><span>;</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>java.nio.file.Files</span><span>;</span></div></div><div><div><div>5</div></div><div><span>import</span><span> </span><span>java.nio.file.Path</span><span>;</span></div></div><div><div><div>6</div></div><div><span>import</span><span> </span><span>java.nio.file.StandardOpenOption</span><span>;</span></div></div><div><div><div>7</div></div><div><span>import</span><span> </span><span>java.util.</span><span>*</span><span>;</span></div></div><div><div><div>8</div></div><div><span>import</span><span> </span><span>java.util.stream.Collectors</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>StudentSystem</span><span> </span></span><span>{</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>// —— 数据模型（record + 封装）——</span></div></div><div><div><div>13</div></div><div><span>    </span><span>record</span><span> </span><span>Student</span><span>(</span><span>String</span><span><span> id</span><span>,</span><span> </span></span><span>String</span><span><span> name</span><span>,</span><span> </span></span><span>String</span><span><span> className</span><span>,</span><span> </span></span><span>double</span><span><span> score) </span><span>{</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>String</span><span> </span><span>toCsv</span><span><span>()</span><span> </span><span>{ </span></span><span>return</span><span> </span><span>String</span><span>.</span><span>join</span><span>(</span><span>","</span><span>, id, name, className, </span><span>String</span><span>.</span><span>valueOf</span><span>(score)); }</span></div></div><div><div><div>15</div></div><div><span>        </span><span>static</span><span> </span><span>Student</span><span> </span><span>fromCsv</span><span>(</span><span>String</span><span><span> </span><span>line</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>16</div></div><div><span>            </span><span>String</span><span><span>[] </span><span>p</span><span> </span></span><span><span>=</span><span> </span></span><span>line</span><span>.</span><span>split</span><span>(</span><span>","</span><span><span>, </span><span>-</span></span><span>1</span><span>);</span></div></div><div><div><div>17</div></div><div><span>            </span><span>if</span><span> (</span><span>p</span><span>.</span><span>length</span><span><span> </span><span>!=</span><span> </span></span><span>4</span><span>) </span><span>return</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>18</div></div><div><span>            </span><span>try</span><span> { </span><span>return</span><span> </span><span>new</span><span> </span><span>Student</span><span>(p[</span><span>0</span><span>], p[</span><span>1</span><span>], p[</span><span>2</span><span>], </span><span>Double</span><span>.</span><span>parseDouble</span><span>(p[</span><span>3</span><span>])); }</span></div></div><div><div><div>19</div></div><div><span>            </span><span>catch</span><span> (</span><span>NumberFormatException</span><span><span> </span><span>e</span><span>) { </span></span><span>return</span><span> </span><span>null</span><span>; }</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>    </span><span>// —— 业务异常（第九篇）——</span></div></div><div><div><div>24</div></div><div><span>    </span><span>static</span><span> </span><span>class</span><span><span> </span><span>SysException</span><span> </span></span><span>extends</span><span><span> </span><span>RuntimeException</span><span> </span></span><span>{</span></div></div><div><div><div>25</div></div><div><span>        </span><span>SysException</span><span>(</span><span>String</span><span><span> </span><span>msg</span><span>)</span><span> </span><span>{ </span></span><span>super</span><span>(msg); }</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>    </span><span>// —— 服务层：集合 + Stream（第八篇 + 本篇）——</span></div></div><div><div><div>29</div></div><div><span>    </span><span>static</span><span> </span><span>class</span><span><span> </span><span>Service</span><span> </span></span><span>{</span></div></div><div><div><div>30</div></div><div><span>        </span><span>private</span><span> </span><span>final</span><span> </span><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Student</span><span><span>&gt;</span><span> data </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>LinkedHashMap</span><span><span>&lt;&gt;</span><span>()</span><span>;</span></span></div></div><div><div><div>31</div></div><div><span>        </span><span>private</span><span> </span><span>final</span><span> </span><span>Path</span><span> file </span><span><span>=</span><span> </span></span><span>Path</span><span>.</span><span>of</span><span>(</span><span>"students.csv"</span><span>);</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>        </span><span>Service</span><span><span>()</span><span> </span><span>{ </span></span><span>load</span><span>(); }</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>        </span><span>Student</span><span> </span><span>add</span><span>(</span><span>String</span><span><span> </span><span>name</span><span>, </span></span><span>String</span><span><span> </span><span>className</span><span>, </span></span><span>double</span><span><span> </span><span>score</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>36</div></div><div><span>            </span><span>if</span><span><span> (score </span><span>&lt;</span><span> </span></span><span>0</span><span><span> </span><span>||</span><span> score </span><span>&gt;</span><span> </span></span><span>100</span><span>)</span></div></div><div><div><div>37</div></div><div><span>                </span><span>throw</span><span> </span><span>new</span><span> </span><span>SysException</span><span>(</span><span>"成绩必须在 0~100: "</span><span><span> </span><span>+</span><span> score);</span></span></div></div><div><div><div>38</div></div><div><span>            </span><span>String</span><span><span> </span><span>id</span><span> </span></span><span><span>=</span><span> </span></span><span>"S"</span><span><span> </span><span>+</span><span> (</span></span><span>data</span><span>.</span><span>size</span><span><span>() </span><span>+</span><span> </span></span><span>1001</span><span>);</span></div></div><div><div><div>39</div></div><div><span>            </span><span>Student</span><span><span> </span><span>s</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Student</span><span>(id, name, className, score);</span></div></div><div><div><div>40</div></div><div><span>            </span><span>data</span><span>.</span><span>put</span><span>(id, s);</span></div></div><div><div><div>41</div></div><div><span>            </span><span>save</span><span>();</span></div></div><div><div><div>42</div></div><div><span>            </span><span>return</span><span> s;</span></div></div><div><div><div>43</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>        </span><span>void</span><span> </span><span>remove</span><span>(</span><span>String</span><span><span> </span><span>id</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>46</div></div><div><span>            </span><span>if</span><span> (</span><span>data</span><span>.</span><span>remove</span><span><span>(id) </span><span>==</span><span> </span></span><span>null</span><span>)</span></div></div><div><div><div>47</div></div><div><span>                </span><span>throw</span><span> </span><span>new</span><span> </span><span>SysException</span><span>(</span><span>"学号不存在: "</span><span><span> </span><span>+</span><span> id);</span></span></div></div><div><div><div>48</div></div><div><span>            </span><span>save</span><span>();</span></div></div><div><div><div>49</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;</span><span> </span></span><span>ranking</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>52</div></div><div><span>            </span><span>return</span><span> </span><span>data</span><span>.</span><span>values</span><span>().</span><span>stream</span><span>()</span></div></div><div><div><div>53</div></div><div><span><span>                    </span></span><span>.</span><span>sorted</span><span>(</span><span>Comparator</span><span>.</span><span>comparingDouble</span><span>(Student</span><span>::</span><span>score).</span><span>reversed</span><span>())</span></div></div><div><div><div>54</div></div><div><span><span>                    </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>toList</span><span>());</span></div></div><div><div><div>55</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>56</div></div><div>
</div></div><div><div><div>57</div></div><div><span>        </span><span>Map</span><span>&lt;</span><span>String</span><span><span>,</span><span> </span></span><span>Double</span><span><span>&gt;</span><span> </span></span><span>classAverages</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>58</div></div><div><span>            </span><span>return</span><span> </span><span>data</span><span>.</span><span>values</span><span>().</span><span>stream</span><span>()</span></div></div><div><div><div>59</div></div><div><span><span>                    </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>groupingBy</span><span>(Student</span><span>::</span><span>className,</span></div></div><div><div><div>60</div></div><div><span>                             </span><span>Collectors</span><span>.</span><span>averagingDouble</span><span>(Student</span><span>::</span><span>score)));</span></div></div><div><div><div>61</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>        </span><span>List</span><span>&lt;</span><span>Student</span><span><span>&gt;</span><span> </span></span><span>search</span><span>(</span><span>String</span><span><span> </span><span>kw</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>64</div></div><div><span>            </span><span>return</span><span> </span><span>data</span><span>.</span><span>values</span><span>().</span><span>stream</span><span>()</span></div></div><div><div><div>65</div></div><div><span><span>                    </span></span><span>.</span><span>filter</span><span>(s </span><span>-&gt;</span><span> </span><span>s</span><span>.</span><span>name</span><span>().</span><span>contains</span><span><span>(kw) </span><span>||</span><span> </span></span><span>s</span><span>.</span><span>id</span><span>().</span><span>contains</span><span>(kw))</span></div></div><div><div><div>66</div></div><div><span><span>                    </span></span><span>.</span><span>collect</span><span>(</span><span>Collectors</span><span>.</span><span>toList</span><span>());</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>68</div></div><div>
</div></div><div><div><div>69</div></div><div><span>        </span><span>// —— 持久化（第十篇）——</span></div></div><div><div><div>70</div></div><div><span>        </span><span>private</span><span> </span><span>void</span><span> </span><span>save</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>71</div></div><div><span>            </span><span>try</span><span> {</span></div></div><div><div><div>72</div></div><div><span>                </span><span>Files</span><span>.</span><span>write</span><span>(file,</span></div></div><div><div><div>73</div></div><div><span>                        </span><span>data</span><span>.</span><span>values</span><span>().</span><span>stream</span><span>().</span><span>map</span><span>(Student</span><span>::</span><span>toCsv).</span><span>toList</span><span>(),</span></div></div><div><div><div>74</div></div><div><span>                        </span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>,</span></div></div><div><div><div>75</div></div><div><span>                        </span><span>StandardOpenOption</span><span>.</span><span>CREATE</span><span>,</span></div></div><div><div><div>76</div></div><div><span>                        </span><span>StandardOpenOption</span><span>.</span><span>TRUNCATE_EXISTING</span><span>);</span></div></div><div><div><div>77</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>78</div></div><div><span>                </span><span>throw</span><span> </span><span>new</span><span> </span><span>SysException</span><span>(</span><span>"保存失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>79</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>80</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span>        </span><span>private</span><span> </span><span>void</span><span> </span><span>load</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>83</div></div><div><span>            </span><span>if</span><span><span> (</span><span>!</span></span><span>Files</span><span>.</span><span>exists</span><span>(file)) </span><span>return</span><span>;</span></div></div><div><div><div>84</div></div><div><span>            </span><span>try</span><span> {</span></div></div><div><div><div>85</div></div><div><span>                </span><span>Files</span><span>.</span><span>readAllLines</span><span>(file, </span><span>StandardCharsets</span><span>.</span><span>UTF_8</span><span>).</span><span>stream</span><span>()</span></div></div><div><div><div>86</div></div><div><span><span>                     </span></span><span>.</span><span>map</span><span>(Student</span><span>::</span><span>fromCsv)</span></div></div><div><div><div>87</div></div><div><span><span>                     </span></span><span>.</span><span>filter</span><span>(Objects</span><span>::</span><span>nonNull)</span></div></div><div><div><div>88</div></div><div><span><span>                     </span></span><span>.</span><span>forEach</span><span>(s </span><span>-&gt;</span><span> </span><span>data</span><span>.</span><span>put</span><span>(</span><span>s</span><span>.</span><span>id</span><span>(), s));</span></div></div><div><div><div>89</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>90</div></div><div><span>                </span><span>System</span><span>.</span><span>err</span><span>.</span><span>println</span><span>(</span><span>"加载失败: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>91</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>92</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>93</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>94</div></div><div>
</div></div><div><div><div>95</div></div><div><span>    </span><span>// —— 控制台交互（流程控制 + 异常处理）——</span></div></div><div><div><div>96</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>main</span><span>(</span><span>String</span><span><span>[] </span><span>args</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>97</div></div><div><span>        </span><span>Service</span><span><span> </span><span>svc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Service</span><span>();</span></div></div><div><div><div>98</div></div><div><span>        </span><span>Scanner</span><span><span> </span><span>sc</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Scanner</span><span>(</span><span>System</span><span>.</span><span>in</span><span>);</span></div></div><div><div><div>99</div></div><div>
</div></div><div><div><div>100</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"=== 学生管理系统 ==="</span><span>);</span></div></div><div><div><div>101</div></div><div><span>        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"add 姓名 班级 成绩 | del 学号 | rank | stat | search 关键词 | list | quit"</span><span>);</span></div></div><div><div><div>102</div></div><div>
</div></div><div><div><div>103</div></div><div><span>        </span><span>while</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>104</div></div><div><span>            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>print</span><span>(</span><span>"</span><span>\n</span><span>&gt; "</span><span>);</span></div></div><div><div><div>105</div></div><div><span>            </span><span>String</span><span><span> </span><span>line</span><span> </span></span><span><span>=</span><span> </span></span><span>sc</span><span>.</span><span>nextLine</span><span>().</span><span>trim</span><span>();</span></div></div><div><div><div>106</div></div><div><span>            </span><span>if</span><span> (</span><span>line</span><span>.</span><span>isEmpty</span><span>()) </span><span>continue</span><span>;</span></div></div><div><div><div>107</div></div><div><span>            </span><span>String</span><span><span>[] </span><span>p</span><span> </span></span><span><span>=</span><span> </span></span><span>line</span><span>.</span><span>split</span><span>(</span><span>"</span><span>\\</span><span>s+"</span><span>);</span></div></div><div><div><div>108</div></div><div><span>            </span><span>String</span><span><span> </span><span>cmd</span><span> </span></span><span><span>=</span><span> p[</span></span><span>0</span><span>];</span></div></div><div><div><div>109</div></div><div>
</div></div><div><div><div>110</div></div><div><span>            </span><span>try</span><span> {</span></div></div><div><div><div>111</div></div><div><span>                </span><span>switch</span><span> (cmd) {</span></div></div><div><div><div>112</div></div><div><span>                    </span><span>case</span><span> </span><span>"quit"</span><span> </span><span>-&gt;</span><span> { </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"再见！"</span><span>); </span><span>return</span><span>; }</span></div></div><div><div><div>113</div></div><div><span>                    </span><span>case</span><span> </span><span>"add"</span><span> </span><span>-&gt;</span><span> {</span></div></div><div><div><div>114</div></div><div><span>                        </span><span>if</span><span> (</span><span>p</span><span>.</span><span>length</span><span><span> </span><span>&lt;</span><span> </span></span><span>4</span><span>) </span><span>throw</span><span> </span><span>new</span><span> </span><span>SysException</span><span>(</span><span>"用法: add 姓名 班级 成绩"</span><span>);</span></div></div><div><div><div>115</div></div><div><span>                        </span><span>Student</span><span><span> </span><span>s</span><span> </span></span><span><span>=</span><span> </span></span><span>svc</span><span>.</span><span>add</span><span>(p[</span><span>1</span><span>], p[</span><span>2</span><span>], </span><span>Double</span><span>.</span><span>parseDouble</span><span>(p[</span><span>3</span><span>]));</span></div></div><div><div><div>116</div></div><div><span>                        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"✅ 已添加 "</span><span><span> </span><span>+</span><span> </span></span><span>s</span><span>.</span><span>id</span><span><span>() </span><span>+</span><span> </span></span><span>" "</span><span><span> </span><span>+</span><span> </span></span><span>s</span><span>.</span><span>name</span><span>());</span></div></div><div><div><div>117</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>118</div></div><div><span>                    </span><span>case</span><span> </span><span>"del"</span><span> </span><span>-&gt;</span><span> {</span></div></div><div><div><div>119</div></div><div><span>                        </span><span>svc</span><span>.</span><span>remove</span><span>(p[</span><span>1</span><span>]);</span></div></div><div><div><div>120</div></div><div><span>                        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"🗑 已删除"</span><span>);</span></div></div><div><div><div>121</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>122</div></div><div><span>                    </span><span>case</span><span> </span><span>"rank"</span><span> </span><span>-&gt;</span><span> </span><span>svc</span><span>.</span><span>ranking</span><span>().</span><span>forEach</span><span>(s </span><span>-&gt;</span></div></div><div><div><div>123</div></div><div><span>                            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"  %-6s %-6s %-4s %.1f%n"</span><span>,</span></div></div><div><div><div>124</div></div><div><span>                                    </span><span>s</span><span>.</span><span>id</span><span>(), </span><span>s</span><span>.</span><span>name</span><span>(), </span><span>s</span><span>.</span><span>className</span><span>(), </span><span>s</span><span>.</span><span>score</span><span>()));</span></div></div><div><div><div>125</div></div><div><span>                    </span><span>case</span><span> </span><span>"stat"</span><span> </span><span>-&gt;</span><span> {</span></div></div><div><div><div>126</div></div><div><span>                        </span><span>svc</span><span>.</span><span>classAverages</span><span>().</span><span>forEach</span><span>((cls, avg) </span><span>-&gt;</span></div></div><div><div><div>127</div></div><div><span>                                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>printf</span><span>(</span><span>"  %s: 平均 %.1f%n"</span><span>, cls, avg));</span></div></div><div><div><div>128</div></div><div><span>                        </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"  全员均分: "</span><span><span> </span><span>+</span></span></div></div><div><div><div>129</div></div><div><span>                                </span><span>svc</span><span>.</span><span>ranking</span><span>().</span><span>stream</span><span>()</span></div></div><div><div><div>130</div></div><div><span><span>                                   </span></span><span>.</span><span>mapToDouble</span><span>(Student</span><span>::</span><span>score).</span><span>average</span><span>().</span><span>orElse</span><span>(</span><span>0</span><span>));</span></div></div><div><div><div>131</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>132</div></div><div><span>                    </span><span>case</span><span> </span><span>"search"</span><span> </span><span>-&gt;</span><span> </span><span>svc</span><span>.</span><span>search</span><span>(p[</span><span>1</span><span>]).</span><span>forEach</span><span>(s </span><span>-&gt;</span></div></div><div><div><div>133</div></div><div><span>                            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"  "</span><span><span> </span><span>+</span><span> s));</span></span></div></div><div><div><div>134</div></div><div><span>                    </span><span>case</span><span> </span><span>"list"</span><span> </span><span>-&gt;</span><span> </span><span>svc</span><span>.</span><span>ranking</span><span>().</span><span>forEach</span><span>(s </span><span>-&gt;</span></div></div><div><div><div>135</div></div><div><span>                            </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"  "</span><span><span> </span><span>+</span><span> s));</span></span></div></div><div><div><div>136</div></div><div><span>                    </span><span>default</span><span> </span><span>-&gt;</span><span> </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"未知命令"</span><span>);</span></div></div><div><div><div>137</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>138</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>SysException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>139</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"❌ "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>140</div></div><div><span><span>            </span></span><span>} </span><span>catch</span><span> (</span><span>Exception</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>141</div></div><div><span>                </span><span>System</span><span>.</span><span>out</span><span>.</span><span>println</span><span>(</span><span>"输入格式错误: "</span><span><span> </span><span>+</span><span> </span></span><span>e</span><span>.</span><span>getMessage</span><span>());</span></div></div><div><div><div>142</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>143</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>144</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>145</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>运行演示</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&gt; add 小明 一班 90</span></div></div><div><div><div>2</div></div><div><span>✅ 已添加 S1001 小明</span></div></div><div><div><div>3</div></div><div><span>&gt; add 小红 二班 85</span></div></div><div><div><div>4</div></div><div><span>✅ 已添加 S1002 小红</span></div></div><div><div><div>5</div></div><div><span>&gt; rank</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>S1001  小明   一班  90.0</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>S1002  小红   二班  85.0</span></div></div><div><div><div>8</div></div><div><span>&gt; stat</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>一班: 平均 90.0</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>二班: 平均 85.0</span></div></div><div><div><div>11</div></div><div><span>&gt; del S1002</span></div></div><div><div><div>12</div></div><div><span>🗑 已删除</span></div></div><div><div><div>13</div></div><div><span>&gt; quit</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>涉及知识清单</strong>：record（现代数据类）、LinkedHashMap、Stream 排序/分组/统计、Collectors 全家桶、自定义异常、Files 持久化、switch 表达式、Scanner 交互。这就是”全系列合体”。</p></section>
<section><h2>三、系列总结<a href="#三系列总结"><span>#</span></a></h2>

<table><thead><tr><th>篇</th><th>主题</th><th>关键收获</th></tr></thead><tbody><tr><td>1</td><td>环境与第一个程序</td><td>JDK/JVM、IDEA、main 结构</td></tr><tr><td>2</td><td>语法与运算符</td><td>八大类型、转换陷阱、printf</td></tr><tr><td>3</td><td>流程控制</td><td>switch 表达式、标签跳转</td></tr><tr><td>4</td><td>方法与数组</td><td>重载、值传递本质、Arrays 工具</td></tr><tr><td>5</td><td>面向对象（上）</td><td>封装、JavaBean、static、包与权限</td></tr><tr><td>6</td><td>面向对象（下）</td><td>继承、多态、接口、equals/hashCode</td></tr><tr><td>7</td><td>核心类库</td><td>String 不可变、包装类、BigDecimal、日期</td></tr><tr><td>8</td><td>集合框架</td><td>List/Set/Map、merge 计数、Comparator</td></tr><tr><td>9</td><td>异常处理</td><td>受检/非受检、try-with-resources</td></tr><tr><td>10</td><td>文件 IO</td><td>Files 一行流、编码、CSV 持久化</td></tr><tr><td>11</td><td>多线程与 Lambda</td><td>线程池、synchronized、函数式接口</td></tr><tr><td>12</td><td>Stream 与实战（本篇）</td><td>流水线、Collectors、综合项目</td></tr></tbody></table><p><strong>下一步方向</strong>：Spring Boot 后端开发、Android 应用、大数据生态（Hadoop/Spark 均是 Java 系）、或深入 JVM 原理。做出项目欢迎投稿本站！</p></section>
<section><h2>小练习（毕业设计）<a href="#小练习毕业设计"><span>#</span></a></h2><ol>
<li>学生系统加”修改成绩”与”按班级删除”命令</li>
<li>把存储从 CSV 升级为 JSON（手写简易序列化或引入 Gson）</li>
<li>加”异步导出报表”功能：线程池执行导出，导出完成后提示（多线程 + Future）</li>
<li>用 Stream 一行实现：求数组中”偶数的平方的平均值”</li>
<li>（三系列横向）用 Python 与 C++ 各重写一个命令行 Todo，对比三种语言的代码量与思路差异</li>
</ol><hr /><p><em>本系列为 Cyber先锋社原创教程，共 12 篇完结。至此本站 Python（11篇）/ C++（12篇）/ Java（12篇）三大入门系列全部完结，欢迎在留言板晒毕业设计！</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-01/</id>
      <title type="text">Python 入门教程（一）：从安装到第一个程序</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-01/"/>
      <summary type="text">零基础开启 Python 之旅：安装解释器、认识交互式环境、写出第一个程序、理解变量与基本数据类型。本篇是编程语言入门系列的第一步。</summary>
      <content type="html"><![CDATA[<section><h2>为什么从 Python 开始<a href="#为什么从-python-开始"><span>#</span></a></h2><p>在所有编程语言中，Python 几乎是公认最适合入门的语言：语法接近自然英语、不用操心内存和类型声明的细节、装好就能跑，而且它在数据分析、人工智能、自动化脚本、Web 开发领域都是主流工具。学会 Python，等于拿到了信息技术世界的一把万能钥匙。</p></section>
<section><h2>安装 Python<a href="#安装-python"><span>#</span></a></h2><section><h3>Windows<a href="#windows"><span>#</span></a></h3><ol>
<li>访问 <a href="https://www.python.org/downloads/" target="_blank">python.org/downloads</a> 下载最新版安装包（3.x 系列）</li>
<li>运行安装程序，<strong>务必勾选 “Add Python to PATH”</strong>，这是新手最常见的翻车点</li>
<li>安装完成后打开命令提示符（Win+R 输入 <code>cmd</code>），验证：</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>python</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>看到 <code>Python 3.x.x</code> 即安装成功。</p></section><section><h3>macOS<a href="#macos"><span>#</span></a></h3><p>系统自带 Python，但版本可能较旧，推荐用 Homebrew 安装最新版：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>brew</span><span> </span><span>install</span><span> </span><span>python</span></div></div><div><div><div>2</div></div><div><span>python3</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Linux（Ubuntu/Debian）<a href="#linuxubuntudebian"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span><span> &amp;&amp; </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>python3</span><span> </span><span>python3-pip</span></div></div><div><div><div>2</div></div><div><span>python3</span><span> </span><span>--version</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Tip</div></div><div><p>Windows 上命令是 <code>python</code>，macOS/Linux 上通常是 <code>python3</code>，本文后续统一写 <code>python</code>，请按自己的系统对应。</p></div></div></section></section>
<section><h2>第一个程序：Hello World<a href="#第一个程序hello-world"><span>#</span></a></h2><p>打开命令行，输入 <code>python</code> 进入<strong>交互式环境</strong>（出现 <code>&gt;&gt;&gt;</code> 提示符），然后输入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>&gt;&gt;&gt;</span><span> </span></span><span>print</span><span>(</span><span>"Hello, Cyber先锋社!"</span><span>)</span></div></div><div><div><div>2</div></div><div><span>Hello, Cyber先锋社!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>回车即出结果——这就是交互式环境的好处：<strong>即写即测</strong>，非常适合学习阶段做小实验。输入 <code>exit()</code> 可退出。</p><p>也可以把代码存成文件。新建 <code>hello.py</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>"Hello, Cyber先锋社!"</span><span>)</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>"我的第一个 Python 程序"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在命令行运行：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>python</span><span> </span><span>hello.py</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Note</div></div><div><p><code>.py</code> 是 Python 源文件的扩展名。用 VS Code、PyCharm 等编辑器打开编写体验更好。</p></div></div></section>
<section><h2>变量与数据类型<a href="#变量与数据类型"><span>#</span></a></h2><section><h3>变量：给数据贴标签<a href="#变量给数据贴标签"><span>#</span></a></h3><p>变量就是一个”名字标签”，指向内存里的某个数据。Python 里不需要声明类型，直接赋值即可：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>name </span><span>=</span><span> </span></span><span>"小明"</span><span>        </span><span># 字符串 str</span></div></div><div><div><div>2</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>18</span><span>             </span><span># 整数 int</span></div></div><div><div><div>3</div></div><div><span><span>height </span><span>=</span><span> </span></span><span>1.75</span><span>        </span><span># 浮点数 float</span></div></div><div><div><div>4</div></div><div><span><span>is_student </span><span>=</span><span> </span></span><span>True</span><span>    </span><span># 布尔值 bool</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>用 <code>type()</code> 函数可以查看任何数据的类型：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>&gt;&gt;&gt;</span><span> </span></span><span>type</span><span>(age)</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>class</span><span> </span><span>'int'</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>常用数据类型速览<a href="#常用数据类型速览"><span>#</span></a></h3>

<table><thead><tr><th>类型</th><th>名称</th><th>示例</th><th>用途</th></tr></thead><tbody><tr><td><code>int</code></td><td>整数</td><td><code>42</code>, <code>-7</code></td><td>计数、索引</td></tr><tr><td><code>float</code></td><td>浮点数</td><td><code>3.14</code></td><td>小数运算</td></tr><tr><td><code>str</code></td><td>字符串</td><td><code>"hello"</code></td><td>文本处理</td></tr><tr><td><code>bool</code></td><td>布尔值</td><td><code>True</code>, <code>False</code></td><td>逻辑判断</td></tr></tbody></table></section><section><h3>基本运算<a href="#基本运算"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> </span></span><span>10</span></div></div><div><div><div>2</div></div><div><span><span>b </span><span>=</span><span> </span></span><span>3</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>print</span><span><span>(a </span><span>+</span><span> b)    </span></span><span># 13  加</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(a </span><span>-</span><span> b)    </span></span><span># 7   减</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(a </span><span>*</span><span> b)    </span></span><span># 30  乘</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(a </span><span>/</span><span> b)    </span></span><span># 3.3333... 除（结果一定是 float）</span></div></div><div><div><div>8</div></div><div><span>print</span><span><span>(a </span><span>//</span><span> b)   </span></span><span># 3   整除（舍去小数）</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(a </span><span>%</span><span> b)    </span></span><span># 1   取余数</span></div></div><div><div><div>10</div></div><div><span>print</span><span><span>(a </span><span>**</span><span> b)   </span></span><span># 1000 幂运算</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>字符串操作<a href="#字符串操作"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>"Cyber Pioneer"</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>len</span><span>(s))           </span><span># 13，字符串长度</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(s.</span><span>upper</span><span>())        </span></span><span># CYBER PIONEER</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(s.</span><span>lower</span><span>())        </span></span><span># cyber pioneer</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(s </span><span>+</span><span> </span></span><span>" Club"</span><span>)      </span><span># 拼接：Cyber Pioneer Club</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>s</span><span>}</span><span> 欢迎你"</span><span>)    </span><span># f-string 格式化（推荐）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>f-string</code> 是 Python 3.6+ 的格式化语法，在字符串前加 <code>f</code>，用 <code>{}</code> 嵌入变量，是现代 Python 的标准写法。</p></section></section>
<section><h2>输入与输出<a href="#输入与输出"><span>#</span></a></h2><p>程序要与人交互，就需要输入输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>name </span><span>=</span><span> </span></span><span>input</span><span>(</span><span>"你叫什么名字？"</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>int</span><span>(</span><span>input</span><span>(</span><span>"你多大了？"</span><span>))   </span><span># input 返回的是字符串，转成整数</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span>，你好！明年你就 </span><span>{</span><span><span>age </span><span>+</span><span> </span></span><span>1}</span><span> 岁了"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><code>input()</code> 的返回值<strong>永远是字符串</strong>。要做数学运算必须先转换：<code>int()</code> 转整数、<code>float()</code> 转浮点数。忘记转换是新手第二大翻车点。</p></div></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>定义变量保存你的姓名、年龄、专业，用 f-string 输出一段自我介绍</li>
<li>计算并输出 <code>123 ÷ 7</code> 的商（整除）和余数</li>
<li>让用户输入两个数，输出它们的和、差、积、商</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>Python 通过解释器直接运行，交互式环境适合边学边试</li>
<li>变量无需声明类型，赋值即创建</li>
<li>四大数据类型：<code>int</code> / <code>float</code> / <code>str</code> / <code>bool</code></li>
<li><code>input()</code> 返回字符串，运算前记得转换类型</li>
</ul><p><strong>下一篇</strong>：条件判断与循环——让程序学会”思考”和”重复劳动”。</p><hr /><p><em>本系列为 Cyber先锋社原创教程，参考业界通用知识体系编写。有问题欢迎在留言板讨论！</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-02/</id>
      <title type="text">Python 入门教程（二）：运算符与字符串详解</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-02/"/>
      <summary type="text">详解 Python 全部七类运算符（算术/比较/赋值/逻辑/成员/身份/位运算）与字符串的索引切片、常用方法、格式化输出，配套大量可运行示例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>上一篇我们让程序”跑了起来”，本篇把两块地基打牢：<strong>运算符</strong>（程序怎么算）和<strong>字符串</strong>（文本怎么处理）。这两块内容贯穿所有后续教程，务必动手把每个示例跑一遍。</p></section>
<section><h2>一、运算符全解<a href="#一运算符全解"><span>#</span></a></h2><p>Python 有七类运算符，逐一来看。</p><section><h3>1. 算术运算符<a href="#1-算术运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a, b </span><span>=</span><span> </span></span><span>10</span><span>, </span><span>3</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span><span>(a </span><span>+</span><span> b)    </span></span><span># 13    加</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(a </span><span>-</span><span> b)    </span></span><span># 7     减</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(a </span><span>*</span><span> b)    </span></span><span># 30    乘</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(a </span><span>/</span><span> b)    </span></span><span># 3.3333333333333335  除，结果一定是 float</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(a </span><span>//</span><span> b)   </span></span><span># 3     整除（向下取整）</span></div></div><div><div><div>8</div></div><div><span>print</span><span><span>(a </span><span>%</span><span> b)    </span></span><span># 1     取模（余数）</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(a </span><span>**</span><span> b)   </span></span><span># 1000  幂</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>三个易错点</strong>：</p><ol>
<li><code>/</code> 永远返回 float，哪怕能整除：<code>10 / 2</code> 得 <code>5.0</code></li>
<li><code>//</code> 是<strong>向下取整</strong>，负数时要小心：</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span><span>(</span><span>-</span></span><span>10</span><span><span> </span><span>//</span><span> </span></span><span>3</span><span>)   </span><span># -4  （不是 -3！向负无穷方向取）</span></div></div><div><div><div>2</div></div><div><span>print</span><span><span>(</span><span>-</span></span><span>10</span><span><span> </span><span>%</span><span> </span></span><span>3</span><span>)    </span><span># 2   （余数符号跟除数一致）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>浮点数有精度问题，这是所有语言的通病：</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>0.1</span><span><span> </span><span>+</span><span> </span></span><span>0.2</span><span>)            </span><span># 0.30000000000000004</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>0.1</span><span><span> </span><span>+</span><span> </span></span><span>0.2</span><span><span> </span><span>==</span><span> </span></span><span>0.3</span><span>)     </span><span># False！</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>需要精确计算（如金额）时用 <code>decimal</code> 模块：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> decimal </span><span>import</span><span> Decimal</span></div></div><div><div><div>2</div></div><div><span>print</span><span><span>(</span><span>Decimal</span><span>(</span></span><span>"0.1"</span><span><span>) </span><span>+</span><span> </span><span>Decimal</span><span>(</span></span><span>"0.2"</span><span><span>) </span><span>==</span><span> </span><span>Decimal</span><span>(</span></span><span>"0.3"</span><span>))   </span><span># True</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 比较运算符<a href="#2-比较运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>3</span><span><span> </span><span>&gt;</span><span> </span></span><span>2</span><span>)      </span><span># True</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>3</span><span><span> </span><span>&lt;</span><span> </span></span><span>2</span><span>)      </span><span># False</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>3</span><span><span> </span><span>&gt;=</span><span> </span></span><span>3</span><span>)     </span><span># True</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>3</span><span><span> </span><span>==</span><span> </span></span><span>3</span><span>)     </span><span># True   相等是两个等号！</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>3</span><span><span> </span><span>!=</span><span> </span></span><span>3</span><span>)     </span><span># False  不等号</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p>新手第一大坑：<code>=</code> 是赋值，<code>==</code> 才是比较。写 <code>if x = 3:</code> 会直接报语法错误——这是 Python 刻意设计的保护。</p></div></div><p>Python 支持链式比较，很优雅：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>20</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>18</span><span><span> </span><span>&lt;=</span><span> age </span><span>&lt;</span><span> </span></span><span>60</span><span>)   </span><span># True，等价于 18 &lt;= age and age &lt; 60</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 赋值运算符<a href="#3-赋值运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>x </span><span>=</span><span> </span></span><span>10</span></div></div><div><div><div>2</div></div><div><span><span>x </span><span>+=</span><span> </span></span><span>5</span><span>    </span><span># x = x + 5 → 15</span></div></div><div><div><div>3</div></div><div><span><span>x </span><span>-=</span><span> </span></span><span>3</span><span>    </span><span># 12</span></div></div><div><div><div>4</div></div><div><span><span>x </span><span>*=</span><span> </span></span><span>2</span><span>    </span><span># 24</span></div></div><div><div><div>5</div></div><div><span><span>x </span><span>//=</span><span> </span></span><span>5</span><span>   </span><span># 4</span></div></div><div><div><div>6</div></div><div><span><span>x </span><span>**=</span><span> </span></span><span>2</span><span>   </span><span># 16</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>多重赋值与解包</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a, b </span><span>=</span><span> </span></span><span>1</span><span>, </span><span>2</span><span>          </span><span># 同时赋值</span></div></div><div><div><div>2</div></div><div><span><span>a, b </span><span>=</span><span> b, a          </span></span><span># 经典：一行交换两个变量（无需临时变量）</span></div></div><div><div><div>3</div></div><div><span><span>x </span><span>=</span><span> y </span><span>=</span><span> </span></span><span>0</span><span>            </span><span># 链式赋值，x 和 y 都是 0</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>first, </span><span>*</span><span>rest </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>]   </span><span># 星号解包：first=1, rest=[2,3,4]</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(first, rest)   </span><span># 1 [2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. 逻辑运算符<a href="#4-逻辑运算符"><span>#</span></a></h3><p>Python 用英文单词而非符号：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>20</span></div></div><div><div><div>2</div></div><div><span><span>has_card </span><span>=</span><span> </span></span><span>True</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>print</span><span><span>(age </span><span>&gt;=</span><span> </span></span><span>18</span><span> </span><span>and</span><span> has_card)    </span><span># True  且</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(age </span><span>&lt;</span><span> </span></span><span>18</span><span> </span><span>or</span><span> has_card)      </span><span># True  或</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>not</span><span> has_card)              </span><span># False 非</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>短路求值</strong>：<code>and</code> 左边为假时右边不再计算，<code>or</code> 左边为真时同理。常用于安全访问：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 列表非空才取第一个元素（若右边执行而列表为空会报错）</span></div></div><div><div><div>2</div></div><div><span><span>nums </span><span>=</span><span> []</span></span></div></div><div><div><div>3</div></div><div><span>if</span><span> nums </span><span>and</span><span> nums[</span><span>0</span><span><span>] </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>"正数"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>真值表速记</strong>（哪些值被视为 False）：</p>

<table><thead><tr><th>假值</th><th>说明</th></tr></thead><tbody><tr><td><code>False</code>、<code>None</code></td><td></td></tr><tr><td><code>0</code>、<code>0.0</code></td><td>数字零</td></tr><tr><td><code>""</code>、<code>[]</code>、<code>{}</code>、<code>()</code>、<code>set()</code></td><td>空容器</td></tr></tbody></table><p>其余一切值都为真，包括 <code>"False"</code> 这个非空字符串。</p></section><section><h3>5. 成员运算符<a href="#5-成员运算符"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>"py"</span><span> </span><span>in</span><span> </span><span>"python"</span><span>)        </span><span># True</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>3</span><span> </span><span>in</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>])          </span><span># True</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>"x"</span><span> </span><span>not</span><span> </span><span>in</span><span> [</span><span>"a"</span><span>, </span><span>"b"</span><span>])   </span><span># True</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>"name"</span><span> </span><span>in</span><span> {</span><span>"name"</span><span>: </span><span>"Tom"</span><span>})   </span><span># True（查的是键）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>6. 身份运算符<a href="#6-身份运算符"><span>#</span></a></h3><p><code>is</code> 比较两个变量是否指向<strong>同一个对象</strong>，<code>==</code> 只比较值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>b </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>3</div></div><div><span>print</span><span><span>(a </span><span>==</span><span> b)    </span></span><span># True  值相等</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(a </span><span>is</span><span> b)    </span><span># False 不是同一个对象</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>c </span><span>=</span><span> a</span></span></div></div><div><div><div>7</div></div><div><span>print</span><span>(c </span><span>is</span><span> a)    </span><span># True  c 和 a 指向同一列表</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Tip</div></div><div><p>判断 None 必须用 <code>is None</code> 而不是 <code>== None</code>，这是 PEP 8 规范。</p></div></div></section><section><h3>7. 位运算符（了解即可）<a href="#7-位运算符了解即可"><span>#</span></a></h3><p>直接对整数的二进制位操作，底层开发、算法优化才会常用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>5</span><span><span> </span><span>&amp;</span><span> </span></span><span>3</span><span>)    </span><span># 1   按位与：0b101 &amp; 0b011 = 0b001</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>5</span><span><span> </span><span>|</span><span> </span></span><span>3</span><span>)    </span><span># 7   按位或</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>5</span><span><span> </span><span>^</span><span> </span></span><span>3</span><span>)    </span><span># 6   按位异或</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>5</span><span><span> </span><span>&lt;&lt;</span><span> </span></span><span>1</span><span>)   </span><span># 10  左移一位相当于 ×2</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>5</span><span><span> </span><span>&gt;&gt;</span><span> </span></span><span>1</span><span>)   </span><span># 2   右移一位相当于 //2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>经典应用</strong>：<code>x &lt;&lt; 1</code> 比 <code>x * 2</code> 快；判断奇偶 <code>x &amp; 1</code>（结果 1 为奇数）。</p></section><section><h3>运算符优先级（简表）<a href="#运算符优先级简表"><span>#</span></a></h3><p>从高到低：<code>**</code> → 一元负号 → <code>* / // %</code> → <code>+ -</code> → 比较运算 → <code>not</code> → <code>and</code> → <code>or</code>。<strong>记不住就加括号</strong>，括号永远最清晰。</p></section></section>
<section><h2>二、字符串详解<a href="#二字符串详解"><span>#</span></a></h2><section><h3>字符串的本质：不可变序列<a href="#字符串的本质不可变序列"><span>#</span></a></h3><p>字符串是字符组成的<strong>序列</strong>，可以按位置访问；但它是<strong>不可变的</strong>——任何”修改”都是创建新字符串：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>"CyberPioneer"</span></div></div><div><div><div>2</div></div><div><span>s[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>"c"</span><span>     </span><span># ❌ TypeError！字符串不可修改</span></div></div><div><div><div>3</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>"c"</span><span><span> </span><span>+</span><span> s[</span></span><span>1</span><span>:]   </span><span># ✅ 拼出新字符串</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(s)       </span><span># cyperPioneer</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>索引与切片（重中之重）<a href="#索引与切片重中之重"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>"CyberPioneer"</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 索引：从 0 开始，负数从末尾开始</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(s[</span><span>0</span><span>])     </span><span># C</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(s[</span><span>-</span></span><span>1</span><span>])    </span><span># r</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>len</span><span>(s))   </span><span># 12</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 切片语法 s[起:止:步长]，含头不含尾</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(s[</span><span>0</span><span>:</span><span>5</span><span>])    </span><span># Cyber</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(s[</span><span>5</span><span>:])     </span><span># Pioneer（省略止 = 到结尾）</span></div></div><div><div><div>11</div></div><div><span>print</span><span>(s[:</span><span>5</span><span>])     </span><span># Cyber（省略起 = 从开头）</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(s[::</span><span>2</span><span>])    </span><span># CyePoer（隔一个取一个）</span></div></div><div><div><div>13</div></div><div><span>print</span><span><span>(s[::</span><span>-</span></span><span>1</span><span>])   </span><span># renoiPreyC（经典倒序！）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>切片口诀</strong>：<strong>含头不含尾，省头从头起，省尾到尾止，负步长倒着走</strong>。</p><p>切片越界<strong>不会报错</strong>（索引越界才会）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(s[</span><span>0</span><span>:</span><span>100</span><span>])   </span><span># 整个字符串，不报错</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(s[</span><span>100</span><span>])     </span><span># ❌ IndexError</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>常用内置方法<a href="#常用内置方法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>s </span><span>=</span><span> </span></span><span>" hello Cyber Pioneer "</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># —— 大小写类 ——</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(s.</span><span>strip</span><span>())            </span></span><span># 去两端空白："hello Cyber Pioneer"</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(s.</span><span>upper</span><span>())            </span></span><span># 全大写</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(s.</span><span>lower</span><span>())            </span></span><span># 全小写</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(s.</span><span>title</span><span>())            </span></span><span># 每个单词首字母大写</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(</span><span>"abc"</span><span><span>.</span><span>capitalize</span><span>())   </span></span><span># Abc 首字母大写</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># —— 查找类 ——</span></div></div><div><div><div>11</div></div><div><span><span>t </span><span>=</span><span> </span></span><span>"hello"</span></div></div><div><div><div>12</div></div><div><span>print</span><span><span>(t.</span><span>find</span><span>(</span></span><span>"l"</span><span>))       </span><span># 2  首次出现的索引，找不到返回 -1</span></div></div><div><div><div>13</div></div><div><span>print</span><span><span>(t.</span><span>count</span><span>(</span></span><span>"l"</span><span>))      </span><span># 2  出现次数</span></div></div><div><div><div>14</div></div><div><span>print</span><span><span>(t.</span><span>startswith</span><span>(</span></span><span>"he"</span><span>))   </span><span># True</span></div></div><div><div><div>15</div></div><div><span>print</span><span><span>(t.</span><span>endswith</span><span>(</span></span><span>"lo"</span><span>))     </span><span># True</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># —— 分割与连接 ——</span></div></div><div><div><div>18</div></div><div><span><span>csv </span><span>=</span><span> </span></span><span>"python,cpp,java"</span></div></div><div><div><div>19</div></div><div><span><span>langs </span><span>=</span><span> csv.</span><span>split</span><span>(</span></span><span>","</span><span>)       </span><span># ['python', 'cpp', 'java']</span></div></div><div><div><div>20</div></div><div><span>print</span><span>(</span><span>"-"</span><span><span>.</span><span>join</span><span>(langs))       </span></span><span># python-cpp-java</span></div></div><div><div><div>21</div></div><div><span>print</span><span>(</span><span>"a b  c"</span><span><span>.</span><span>split</span><span>())      </span></span><span># ['a', 'b', 'c']（无参分割自动处理多空格）</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span># —— 替换与判断 ——</span></div></div><div><div><div>24</div></div><div><span>print</span><span>(</span><span>"1+1"</span><span><span>.</span><span>replace</span><span>(</span></span><span>"+"</span><span>, </span><span>"-"</span><span>))    </span><span># 1-1</span></div></div><div><div><div>25</div></div><div><span>print</span><span>(</span><span>"abc123"</span><span><span>.</span><span>isdigit</span><span>())         </span></span><span># False（含字母）</span></div></div><div><div><div>26</div></div><div><span>print</span><span>(</span><span>"12345"</span><span><span>.</span><span>isdigit</span><span>())          </span></span><span># True</span></div></div><div><div><div>27</div></div><div><span>print</span><span>(</span><span>"abc"</span><span><span>.</span><span>isalpha</span><span>())            </span></span><span># True</span></div></div><div><div><div>28</div></div><div><span>print</span><span>(</span><span>"Python"</span><span><span>.</span><span>isupper</span><span>())         </span></span><span># False</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>注意</strong>：这些方法都<strong>不修改原字符串</strong>，而是返回新值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>t </span><span>=</span><span> </span></span><span>"hello"</span></div></div><div><div><div>2</div></div><div><span><span>t.</span><span>upper</span><span>()          </span></span><span># 只是返回了新字符串，没有保存！</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(t)           </span><span># hello（原样）</span></div></div><div><div><div>4</div></div><div><span><span>t </span><span>=</span><span> t.</span><span>upper</span><span>()      </span></span><span># ✅ 要用变量接住</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(t)           </span><span># HELLO</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>三种格式化方式<a href="#三种格式化方式"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>name, score </span><span>=</span><span> </span></span><span>"小明"</span><span>, </span><span>95.5</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 1. f-string（Python 3.6+，现代标准，推荐）</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span> 的成绩是 </span><span>{</span><span>score</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>f</span><span>"及格了吗：</span><span>{</span><span><span>score </span><span>&gt;=</span><span> </span></span><span>60}</span><span>"</span><span>)</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>f</span><span>"保留一位小数：</span><span>{</span><span>score</span><span>:.1f</span><span>}</span><span>"</span><span>)        </span><span># 95.5</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(</span><span>f</span><span>"补零对齐：</span><span>{7</span><span>:03d</span><span>}</span><span>"</span><span>)               </span><span># 007</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(</span><span>f</span><span>"百分比：</span><span>{0.856</span><span>:.1%</span><span>}</span><span>"</span><span>)             </span><span># 85.6%</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>=</span><span>}</span><span> "</span><span>)                        </span><span># name='小明' 调试神器</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 2. format 方法（老代码常见）</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(</span><span>"</span><span>{}</span><span> 的成绩是 </span><span>{}</span><span>"</span><span><span>.</span><span>format</span><span>(name, score))</span></span></div></div><div><div><div>13</div></div><div><span>print</span><span>(</span><span>"</span><span>{1}</span><span> 比 </span><span>{0}</span><span> 高"</span><span><span>.</span><span>format</span><span>(</span></span><span>"小明"</span><span>, </span><span>"小红"</span><span>))   </span><span># 位置参数</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span># 3. % 占位符（最古老，C 语言风格）</span></div></div><div><div><div>16</div></div><div><span>print</span><span>(</span><span>"</span><span>%s</span><span> 的成绩是 </span><span>%.1f</span><span>"</span><span><span> </span><span>%</span><span> (name, score))</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>f-string 常用格式速查</strong>：</p>

<table><thead><tr><th>写法</th><th>作用</th><th>示例结果</th></tr></thead><tbody><tr><td><code>{x:.2f}</code></td><td>两位小数</td><td>3.14</td></tr><tr><td><code>{x:&gt;10}</code></td><td>右对齐宽 10</td><td><code>      hello</code></td></tr><tr><td><code>{x:&lt;10}</code></td><td>左对齐宽 10</td><td><code>hello      </code></td></tr><tr><td><code>{x:^10}</code></td><td>居中宽 10</td><td><code> hello   </code></td></tr><tr><td><code>{x:,}</code></td><td>千分位</td><td>1,234,567</td></tr><tr><td><code>{x:08.2f}</code></td><td>补零宽 8 两位小数</td><td>0003.14</td></tr></tbody></table></section><section><h3>转义字符与原始字符串<a href="#转义字符与原始字符串"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>"第一行</span><span>\n</span><span>第二行"</span><span>)      </span><span># \n 换行</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>"姓名</span><span>\t</span><span>年龄"</span><span>)          </span><span># \t 制表符</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>"他说：</span><span>\"</span><span>你好</span><span>\"</span><span>"</span><span>)       </span><span># \" 输出双引号</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>r</span><span><span>"C:</span><span>\n</span><span>ew</span><span>\t</span><span>able"</span></span><span>)       </span><span># 原始字符串：\n 不转义，正则/路径必备</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>"""多行</span></div></div><div><div><div>6</div></div><div><span>字符串</span></div></div><div><div><div>7</div></div><div><span>写这里"""</span><span>)                    </span><span># 三引号保留换行</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>练手小案例：统计单词<a href="#练手小案例统计单词"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>text </span><span>=</span><span> </span></span><span>"the quick brown fox jumps over the lazy dog the end"</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>words </span><span>=</span><span> text.</span><span>split</span><span>()                    </span></span><span># ['the','quick',...]</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>f</span><span>"总词数: </span><span>{</span><span>len</span><span>(words)</span><span>}</span><span>"</span><span>)          </span><span># 10</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>the_count </span><span>=</span><span> text.</span><span>count</span><span>(</span></span><span>"the"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(</span><span>f</span><span>"the 出现: </span><span>{</span><span>the_count</span><span>}</span><span> 次"</span><span>)       </span><span># 3</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># 每个单词倒序输出</span></div></div><div><div><div>10</div></div><div><span>for</span><span> w </span><span>in</span><span> words:</span></div></div><div><div><div>11</div></div><div><span>    </span><span>print</span><span><span>(w[::</span><span>-</span></span><span>1</span><span>], </span><span>end</span><span>=</span><span>" "</span><span>)</span></div></div><div><div><div>12</div></div><div><span># eht kciuq nworb xof spmuj revo eht yzal god eht dne</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>不用 <code>len()</code>，用循环统计字符串长度（提示：计数器 + <code>for</code> 遍历，下篇揭晓）</li>
<li>实现”回文判断”：<code>"上海自来水来自海上"</code> 正读反读一致（提示：切片倒序比较）</li>
<li>把 <code>"hello world python"</code> 每个单词首字母大写后用 <code>-</code> 连接</li>
<li>用一行代码交换两个变量的值，再用 <code>is</code> 验证小整数缓存的存在（提示：<code>a=1; b=1; a is b</code> 结果与 <code>a=257; b=257; a is b</code> 对比）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>七类运算符：算术/比较/赋值/逻辑/成员/身份/位；<code>/</code> 永远得 float，<code>//</code> 向下取整</li>
<li><code>==</code> 比较值，<code>is</code> 比较身份；判 None 用 <code>is</code></li>
<li>字符串不可变；切片含头不含尾，<code>[::-1]</code> 倒序</li>
<li><code>split</code>/<code>join</code> 是文本处理双璧；字符串方法返回新值需接住</li>
<li>格式化首选 f-string</li>
</ul><p><strong>下一篇</strong>：条件判断与循环——让程序学会思考和重复。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。动手跑一遍所有示例，比读十遍更有用。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-03/</id>
      <title type="text">Python 入门教程（三）：条件判断与循环控制</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-03/"/>
      <summary type="text">完整讲解 if/elif/else 分支结构、while 与 for 循环、range 与 enumerate、break/continue/else 子句、循环嵌套与推导式，用经典练习题巩固流程控制。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>前两篇的程序都是”从头跑到尾”，本篇让程序拥有<strong>判断</strong>（走哪条路）和<strong>重复</strong>（反复做事）的能力。这两者是所有程序逻辑的基石，学完本篇你就能写出真正”有逻辑”的程序了。</p></section>
<section><h2>一、代码块与缩进：Python 的命门<a href="#一代码块与缩进python-的命门"><span>#</span></a></h2><p>Python 不用 <code>{}</code> 園代码块，而用<strong>缩进</strong>（官方推荐 4 个空格）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>60</span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>"及格"</span><span>)          </span><span># 缩进的行属于 if</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(</span><span>"继续努力"</span><span>)      </span><span># 同级缩进 = 同一块代码</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>"无论如何都执行"</span><span>)     </span><span># 不缩进 = 在 if 外面</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div></div></div><ul>
<li>缩进错误（IndentationError）是新手最高频报错。规则：<strong>同级代码缩进必须完全一致</strong>，禁止 tab 和空格混用。把编辑器的 Tab 键设置为”插入 4 空格”一劳永逸。</li>
</ul></section>
<section><h2>二、条件判断<a href="#二条件判断"><span>#</span></a></h2><section><h3>基础 if / else<a href="#基础-if--else"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>score </span><span>=</span><span> </span></span><span>75</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>60</span><span>:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>"及格"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>else</span><span>:</span></div></div><div><div><div>6</div></div><div><span>    </span><span>print</span><span>(</span><span>"不及格"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>多分支 elif<a href="#多分支-elif"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>score </span><span>=</span><span> </span></span><span>85</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>90</span><span>:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>grade </span><span>=</span><span> </span><span>"优秀"</span></div></div><div><div><div>5</div></div><div><span>elif</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>80</span><span>:</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>grade </span><span>=</span><span> </span><span>"良好"</span></div></div><div><div><div>7</div></div><div><span>elif</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>70</span><span>:</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>grade </span><span>=</span><span> </span><span>"中等"</span></div></div><div><div><div>9</div></div><div><span>elif</span><span><span> score </span><span>&gt;=</span><span> </span></span><span>60</span><span>:</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>grade </span><span>=</span><span> </span><span>"及格"</span></div></div><div><div><div>11</div></div><div><span>else</span><span>:</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>grade </span><span>=</span><span> </span><span>"不及格"</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>print</span><span>(</span><span>f</span><span>"等级：</span><span>{</span><span>grade</span><span>}</span><span>"</span><span>)    </span><span># 良好</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>执行逻辑</strong>：从上往下逐个判断，命中即止——所以条件要<strong>从严格到宽松</strong>排列。如果把 <code>score &gt;= 60</code> 放第一个，90 分也会被判”及格”。</p></section><section><h3>嵌套判断<a href="#嵌套判断"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>20</span></div></div><div><div><div>2</div></div><div><span><span>has_id </span><span>=</span><span> </span></span><span>True</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>if</span><span><span> age </span><span>&gt;=</span><span> </span></span><span>18</span><span>:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> has_id:</span></div></div><div><div><div>6</div></div><div><span>        </span><span>print</span><span>(</span><span>"允许进入"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>8</div></div><div><span>        </span><span>print</span><span>(</span><span>"请出示证件"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>else</span><span>:</span></div></div><div><div><div>10</div></div><div><span>    </span><span>print</span><span>(</span><span>"未成年禁止入内"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>嵌套超过两层就该考虑合并条件：<code>if age &gt;= 18 and has_id:</code>。</p></section><section><h3>条件表达式（三元运算符）<a href="#条件表达式三元运算符"><span>#</span></a></h3><p>一行搞定简单二选一：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>age </span><span>=</span><span> </span></span><span>20</span></div></div><div><div><div>2</div></div><div><span><span>status </span><span>=</span><span> </span></span><span>"成年"</span><span> </span><span>if</span><span><span> age </span><span>&gt;=</span><span> </span></span><span>18</span><span> </span><span>else</span><span> </span><span>"未成年"</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(status)     </span><span># 成年</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>match-case（Python 3.10+ 结构化匹配）<a href="#match-casepython-310-结构化匹配"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>handle</span><span>(</span><span>command</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>match</span><span><span> command.</span><span>split</span><span>():</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>case</span><span> [</span><span>"go"</span><span>, direction]:</span></div></div><div><div><div>4</div></div><div><span>            </span><span>return</span><span> </span><span>f</span><span>"向 </span><span>{</span><span>direction</span><span>}</span><span> 移动"</span></div></div><div><div><div>5</div></div><div><span>        </span><span>case</span><span> [</span><span>"look"</span><span>]:</span></div></div><div><div><div>6</div></div><div><span>            </span><span>return</span><span> </span><span>"环顾四周"</span></div></div><div><div><div>7</div></div><div><span>        </span><span>case</span><span> [</span><span>"pick"</span><span>, item, </span><span>"up"</span><span>]:</span></div></div><div><div><div>8</div></div><div><span>            </span><span>return</span><span> </span><span>f</span><span>"捡起 </span><span>{</span><span>item</span><span>}</span><span>"</span></div></div><div><div><div>9</div></div><div><span>        </span><span>case</span><span> _:</span></div></div><div><div><div>10</div></div><div><span>            </span><span>return</span><span> </span><span>"未知指令"</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>print</span><span><span>(</span><span>handle</span><span>(</span></span><span>"go north"</span><span>))     </span><span># 向 north 移动</span></div></div><div><div><div>13</div></div><div><span>print</span><span><span>(</span><span>handle</span><span>(</span></span><span>"pick key up"</span><span>))  </span><span># 捡起 key</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>适合替代长串 elif，<code>case _</code> 是兜底分支。</p></section></section>
<section><h2>三、while 循环：条件驱动<a href="#三while-循环条件驱动"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>count </span><span>=</span><span> </span></span><span>1</span></div></div><div><div><div>2</div></div><div><span>while</span><span><span> count </span><span>&lt;=</span><span> </span></span><span>5</span><span>:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"第 </span><span>{</span><span>count</span><span>}</span><span> 圈"</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>count </span><span>+=</span><span> </span><span>1</span><span>        </span><span># 千万别忘了改变条件，否则死循环！</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>三要素</strong>：初始化（count=1）、条件（&lt;=5）、更新（count+=1）。漏掉第三步就是死循环。</p><section><h3>经典应用：猜数字游戏<a href="#经典应用猜数字游戏"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> random</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>answer </span><span>=</span><span> random.</span><span>randint</span><span>(</span></span><span>1</span><span>, </span><span>100</span><span>)   </span><span># 1~100 随机整数</span></div></div><div><div><div>4</div></div><div><span><span>tries </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>guess </span><span>=</span><span> </span><span>int</span><span>(</span><span>input</span><span>(</span><span>"猜一个 1-100 的数："</span><span>))</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>tries </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span><span> guess </span><span>&lt;</span><span> answer:</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>print</span><span>(</span><span>"小了"</span><span>)</span></div></div><div><div><div>12</div></div><div><span>    </span><span>elif</span><span><span> guess </span><span>&gt;</span><span> answer:</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>print</span><span>(</span><span>"大了"</span><span>)</span></div></div><div><div><div>14</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>15</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"猜对了！用了 </span><span>{</span><span>tries</span><span>}</span><span> 次"</span><span>)</span></div></div><div><div><div>16</div></div><div><span>        </span><span>break</span><span>       </span><span># 跳出循环</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>while True</code> + <code>break</code> 是”先执行、后判断退出”的标准写法。</p></section></section>
<section><h2>四、for 循环：遍历序列<a href="#四for-循环遍历序列"><span>#</span></a></h2><p>for 用来<strong>逐个取出</strong>序列（字符串/列表/字典…）里的元素：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 遍历字符串</span></div></div><div><div><div>2</div></div><div><span>for</span><span> ch </span><span>in</span><span> </span><span>"abc"</span><span>:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(ch)          </span><span># a b c 各一行</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 遍历列表</span></div></div><div><div><div>6</div></div><div><span>for</span><span> lang </span><span>in</span><span> [</span><span>"Python"</span><span>, </span><span>"C++"</span><span>, </span><span>"Java"</span><span>]:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(lang)</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># 遍历字典：items() 同时拿键和值</span></div></div><div><div><div>10</div></div><div><span><span>scores </span><span>=</span><span> {</span></span><span>"小明"</span><span>: </span><span>90</span><span>, </span><span>"小红"</span><span>: </span><span>85</span><span>}</span></div></div><div><div><div>11</div></div><div><span>for</span><span> name, score </span><span>in</span><span><span> scores.</span><span>items</span><span>():</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span>: </span><span>{</span><span>score</span><span>}</span><span>分"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h3>range()：生成数字序列<a href="#range生成数字序列"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>range</span><span>(</span><span>5</span><span>)         </span><span># 0 1 2 3 4        （含头不含尾）</span></div></div><div><div><div>2</div></div><div><span>range</span><span>(</span><span>1</span><span>, </span><span>6</span><span>)      </span><span># 1 2 3 4 5</span></div></div><div><div><div>3</div></div><div><span>range</span><span>(</span><span>0</span><span>, </span><span>10</span><span>, </span><span>2</span><span>)  </span><span># 0 2 4 6 8        （步长 2）</span></div></div><div><div><div>4</div></div><div><span>range</span><span>(</span><span>10</span><span>, </span><span>0</span><span><span>, </span><span>-</span></span><span>1</span><span>) </span><span># 10 9 8 ... 1     （倒序）</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span>, </span><span>4</span><span>):</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>i</span><span>}</span><span> 的平方是 </span><span>{</span><span><span>i</span><span>**</span></span><span>2}</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>enumerate()：同时拿下标和元素<a href="#enumerate同时拿下标和元素"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>langs </span><span>=</span><span> [</span></span><span>"Python"</span><span>, </span><span>"C++"</span><span>, </span><span>"Java"</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 笨办法</span></div></div><div><div><div>4</div></div><div><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>len</span><span>(langs)):</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(i, langs[i])</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 优雅办法</span></div></div><div><div><div>8</div></div><div><span>for</span><span> i, lang </span><span>in</span><span> </span><span>enumerate</span><span>(langs):</span></div></div><div><div><div>9</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"第</span><span>{</span><span>i</span><span>}</span><span>名：</span><span>{</span><span>lang</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>10</div></div><div><span># 第0名：Python ...</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>zip()：并行遍历多个序列<a href="#zip并行遍历多个序列"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>names </span><span>=</span><span> [</span></span><span>"小明"</span><span>, </span><span>"小红"</span><span>, </span><span>"小刚"</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>]</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>for</span><span> name, score </span><span>in</span><span> </span><span>zip</span><span>(names, scores):</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span>: </span><span>{</span><span>score</span><span>}</span><span>分"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、break、continue 与循环 else<a href="#五breakcontinue-与循环-else"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># break：立即终止整个循环</span></div></div><div><div><div>2</div></div><div><span>for</span><span> n </span><span>in</span><span> [</span><span>3</span><span>, </span><span>7</span><span>, </span><span>12</span><span>, </span><span>5</span><span>, </span><span>8</span><span>]:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> n </span><span>&gt;</span><span> </span></span><span>10</span><span>:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"找到大于10的数：</span><span>{</span><span>n</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>        </span><span>break</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># continue：跳过本次，进入下一次</span></div></div><div><div><div>8</div></div><div><span>for</span><span> n </span><span>in</span><span> </span><span>range</span><span>(</span><span>10</span><span>):</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span><span> n </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>10</div></div><div><span>        </span><span>continue</span><span>       </span><span># 偶数跳过</span></div></div><div><div><div>11</div></div><div><span>    </span><span>print</span><span>(n, </span><span>end</span><span>=</span><span>" "</span><span>)  </span><span># 1 3 5 7 9</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>循环的 else 子句</strong>（Python 特色，别处没有）：循环<strong>没被 break 打断</strong>而正常结束才执行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 找质数的标准姿势</span></div></div><div><div><div>2</div></div><div><span><span>n </span><span>=</span><span> </span></span><span>13</span></div></div><div><div><div>3</div></div><div><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>2</span><span>, n):</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> n </span><span>%</span><span> i </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>5</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>n</span><span>}</span><span> 不是质数，能被 </span><span>{</span><span>i</span><span>}</span><span> 整除"</span><span>)</span></div></div><div><div><div>6</div></div><div><span>        </span><span>break</span></div></div><div><div><div>7</div></div><div><span>else</span><span>:</span></div></div><div><div><div>8</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>n</span><span>}</span><span> 是质数"</span><span>)     </span><span># 循环正常跑完没 break → 是质数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>六、循环嵌套：二维世界<a href="#六循环嵌套二维世界"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 九九乘法表</span></div></div><div><div><div>2</div></div><div><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span>, </span><span>10</span><span>):</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> j </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span><span>, i </span><span>+</span><span> </span></span><span>1</span><span>):</span></div></div><div><div><div>4</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>j</span><span>}</span><span>×</span><span>{</span><span>i</span><span>}</span><span>=</span><span>{</span><span><span>i</span><span>*</span><span>j</span></span><span>}</span><span>"</span><span>, </span><span>end</span><span>=</span><span>"</span><span>\t</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>()    </span><span># 每行结束换行</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出（三角形排布）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1×1=1</span></div></div><div><div><div>2</div></div><div><span>1×2=2  2×2=4</span></div></div><div><div><div>3</div></div><div><span>1×3=3  2×3=6  3×3=9</span></div></div><div><div><div>4</div></div><div><span>...（共 9 行）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>嵌套循环次数是<strong>相乘</strong>的：外 3 次内 4 次共 12 次，层数越多越要小心性能。</p></section>
<section><h2>七、推导式：循环的语法糖（进阶必备）<a href="#七推导式循环的语法糖进阶必备"><span>#</span></a></h2><p>用一行表达”遍历 + 处理 + 收集”：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 列表推导式：[表达式 for 变量 in 序列 if 条件]</span></div></div><div><div><div>2</div></div><div><span><span>squares </span><span>=</span><span> [i</span><span>**</span></span><span>2</span><span> </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span>, </span><span>6</span><span>)]</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(squares)          </span><span># [1, 4, 9, 16, 25]</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>evens </span><span>=</span><span> [i </span></span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>20</span><span>) </span><span>if</span><span><span> i </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>]</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(evens)            </span><span># [0, 2, 4, 6, 8, ...]</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 带条件表达式</span></div></div><div><div><div>9</div></div><div><span><span>labels </span><span>=</span><span> [</span></span><span>"偶"</span><span> </span><span>if</span><span><span> i </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> </span><span>else</span><span> </span><span>"奇"</span><span> </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>5</span><span>)]</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(labels)           </span><span># ['偶', '奇', '偶', '奇', '偶']</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span># 字典推导式</span></div></div><div><div><div>13</div></div><div><span><span>word </span><span>=</span><span> </span></span><span>"hello"</span></div></div><div><div><div>14</div></div><div><span><span>freq </span><span>=</span><span> {ch: word.</span><span>count</span><span>(ch) </span></span><span>for</span><span> ch </span><span>in</span><span> </span><span>set</span><span>(word)}</span></div></div><div><div><div>15</div></div><div><span>print</span><span>(freq)             </span><span># {'h': 1, 'e': 1, 'l': 2, 'o': 1}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>可读性原则</strong>：逻辑超过一层嵌套就老实写 for 循环，别炫技。</p></section>
<section><h2>八、经典练习（附思路）<a href="#八经典练习附思路"><span>#</span></a></h2><section><h3>1. 计算 1~100 的和<a href="#1-计算-1100-的和"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>total </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>2</div></div><div><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span>, </span><span>101</span><span>):</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>total </span><span>+=</span><span> i</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(total)    </span><span># 5050</span></div></div><div><div><div>5</div></div><div><span># 数学解法彩蛋：print(100*101//2)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 打印斐波那契数列前 20 项<a href="#2-打印斐波那契数列前-20-项"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a, b </span><span>=</span><span> </span></span><span>0</span><span>, </span><span>1</span></div></div><div><div><div>2</div></div><div><span>for</span><span> _ </span><span>in</span><span> </span><span>range</span><span>(</span><span>20</span><span>):</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(a, </span><span>end</span><span>=</span><span>" "</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>a, b </span><span>=</span><span> b, a </span><span>+</span><span> b</span></div></div><div><div><div>5</div></div><div><span># 0 1 1 2 3 5 8 13 21 ...</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 判断质数（函数版在第六篇会重写）<a href="#3-判断质数函数版在第六篇会重写"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>n </span><span>=</span><span> </span></span><span>int</span><span>(</span><span>input</span><span>(</span><span>"输入一个数："</span><span>))</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> n </span><span>&lt;</span><span> </span></span><span>2</span><span>:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>"不是质数"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>else</span><span>:</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>2</span><span>, </span><span>int</span><span><span>(n</span><span>**</span></span><span>0.5</span><span><span>) </span><span>+</span><span> </span></span><span>1</span><span>):    </span><span># 只需检查到平方根</span></div></div><div><div><div>7</div></div><div><span>        </span><span>if</span><span><span> n </span><span>%</span><span> i </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>8</div></div><div><span>            </span><span>print</span><span>(</span><span>f</span><span>"不是质数，</span><span>{</span><span>n</span><span>}</span><span> = </span><span>{</span><span>i</span><span>}</span><span> × </span><span>{</span><span><span>n</span><span>//</span><span>i</span></span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>            </span><span>break</span></div></div><div><div><div>10</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>11</div></div><div><span>        </span><span>print</span><span>(</span><span>"是质数"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>优化点</strong>：判断到 <code>n**0.5</code> 即可——若 n 有大于平方根的因子，必然对应一个小于平方根的因子。</p></section><section><h3>4. 水仙花数（三位数 = 各位数字立方和）<a href="#4-水仙花数三位数--各位数字立方和"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> n </span><span>in</span><span> </span><span>range</span><span>(</span><span>100</span><span>, </span><span>1000</span><span>):</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>digits </span><span>=</span><span> </span><span>str</span><span>(n)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span> </span><span>int</span><span>(digits[</span><span>0</span><span><span>])</span><span>**</span></span><span>3</span><span><span> </span><span>+</span><span> </span></span><span>int</span><span>(digits[</span><span>1</span><span><span>])</span><span>**</span></span><span>3</span><span><span> </span><span>+</span><span> </span></span><span>int</span><span>(digits[</span><span>2</span><span><span>])</span><span>**</span></span><span>3</span><span><span> </span><span>==</span><span> n:</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>print</span><span>(n)      </span><span># 153 370 371 407</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>输入一个整数，倒序逐位输出（如 1234 → 4 3 2 1），分别用 while 和字符串切片两种方法实现</li>
<li>打印 100 内所有能被 3 整除但不含数字 3 的数（提示：<code>"3" not in str(n)</code>）</li>
<li>用嵌套循环打印直角三角形星号图案（5 行）</li>
<li>用列表推导式生成 1~50 中所有奇数的平方列表</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>缩进即语法：同级一致，4 空格，禁混 tab</li>
<li>if/elif 从严到宽；三元表达式一行二选一；3.10+ 可用 match-case</li>
<li>while 三要素；for 遍历序列；range 生成数字；enumerate 带下标；zip 并行</li>
<li>break 终止 / continue 跳过 / 循环 else 表示”没被 break”</li>
<li>推导式是”遍历+收集”的语法糖，一层以内使用</li>
</ul><p><strong>下一篇</strong>：列表与元组——Python 最常用的数据容器。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。练习务必亲手做，答案写进你自己的代码笔记本。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-04/</id>
      <title type="text">Python 入门教程（四）：列表与元组</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-04/"/>
      <summary type="text">深入 Python 最核心的容器：列表的增删改查全家桶、切片操作、排序与遍历技巧、浅拷贝与深拷贝的坑、元组的不可变特性与解包，附购物车与成绩统计完整案例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>单个变量存单个值，但现实数据往往是”一堆”：一门课的所有成绩、购物车里的商品、通讯录联系人。<strong>列表</strong>和<strong>元组</strong>就是 Python 存放”一堆数据”的基础容器，也是使用频率最高的数据结构。</p></section>
<section><h2>一、列表：可变的有序容器<a href="#一列表可变的有序容器"><span>#</span></a></h2><section><h3>创建与访问<a href="#创建与访问"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 直接创建</span></div></div><div><div><div>2</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>]</span></div></div><div><div><div>3</div></div><div><span><span>empty </span><span>=</span><span> []                     </span></span><span># 空列表</span></div></div><div><div><div>4</div></div><div><span><span>mixed </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>"hello"</span><span>, </span><span>3.14</span><span>, </span><span>True</span><span>]   </span><span># 可以混装类型（但不建议）</span></div></div><div><div><div>5</div></div><div><span><span>nested </span><span>=</span><span> [</span></span><span>1</span><span>, [</span><span>2</span><span>, </span><span>3</span><span>], [</span><span>4</span><span>, [</span><span>5</span><span>]]]     </span><span># 列表可以嵌套</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># list() 从其他序列转换</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(</span><span>list</span><span>(</span><span>"abc"</span><span>))             </span><span># ['a', 'b', 'c']</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(</span><span>list</span><span>(</span><span>range</span><span>(</span><span>5</span><span>)))          </span><span># [0, 1, 2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>索引与切片规则与字符串完全一致（含头不含尾、负数索引）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(scores[</span><span>0</span><span>])      </span><span># 90</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(scores[</span><span>-</span></span><span>1</span><span>])     </span><span># 66</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(scores[</span><span>1</span><span>:</span><span>4</span><span>])    </span><span># [85, 78, 92]</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(scores[::</span><span>-</span></span><span>1</span><span>])   </span><span># 倒序列表</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(</span><span>len</span><span>(scores))    </span><span># 5</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>增：四种方式<a href="#增四种方式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>langs </span><span>=</span><span> [</span></span><span>"Python"</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>langs.</span><span>append</span><span>(</span></span><span>"Java"</span><span>)           </span><span># 尾部追加单个 → ['Python', 'Java']</span></div></div><div><div><div>4</div></div><div><span><span>langs.</span><span>insert</span><span>(</span></span><span>1</span><span>, </span><span>"C++"</span><span>)         </span><span># 指定位置插入 → ['Python', 'C++', 'Java']</span></div></div><div><div><div>5</div></div><div><span><span>langs.</span><span>extend</span><span>([</span></span><span>"Go"</span><span>, </span><span>"Rust"</span><span>])   </span><span># 合并另一个序列 → [..., 'Go', 'Rust']</span></div></div><div><div><div>6</div></div><div><span><span>langs </span><span>+=</span><span> [</span></span><span>"C#"</span><span>]                </span><span># += 等价于 extend</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><code>append</code> 与 <code>extend</code> 的经典坑：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>a.</span><span>append</span><span>([</span></span><span>3</span><span>, </span><span>4</span><span>])    </span><span># [1, 2, [3, 4]]   整个列表作为一个元素！</span></div></div><div><div><div>3</div></div><div><span><span>b </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>]</span></div></div><div><div><div>4</div></div><div><span><span>b.</span><span>extend</span><span>([</span></span><span>3</span><span>, </span><span>4</span><span>])    </span><span># [1, 2, 3, 4]     逐个合并 ✓</span></div></div></code></pre><div><div></div><div></div></div></figure></div></div></div></section><section><h3>删：三种方式<a href="#删三种方式"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>20</span><span>, </span><span>40</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>nums.</span><span>remove</span><span>(</span></span><span>20</span><span>)        </span><span># 按值删：只删第一个匹配项 → [10, 30, 20, 40]</span></div></div><div><div><div>4</div></div><div><span><span>last </span><span>=</span><span> nums.</span><span>pop</span><span>()      </span></span><span># 按索引删并返回该值：40，nums → [10, 30, 20]</span></div></div><div><div><div>5</div></div><div><span><span>first </span><span>=</span><span> nums.</span><span>pop</span><span>(</span></span><span>0</span><span>)    </span><span># 弹出索引0：10</span></div></div><div><div><div>6</div></div><div><span>del</span><span> nums[</span><span>0</span><span>]            </span><span># del 语句删除：30 被删</span></div></div><div><div><div>7</div></div><div><span># nums 现在是 [20]</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># 值不存在时 remove 会报 ValueError，安全写法：</span></div></div><div><div><div>10</div></div><div><span>if</span><span> </span><span>999</span><span> </span><span>in</span><span> nums:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>nums.</span><span>remove</span><span>(</span><span>999</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>改：直接赋值<a href="#改直接赋值"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>]</span></div></div><div><div><div>2</div></div><div><span>scores[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>95</span><span>             </span><span># 单个改</span></div></div><div><div><div>3</div></div><div><span>scores[</span><span>1</span><span>:</span><span>3</span><span><span>] </span><span>=</span><span> [</span></span><span>80</span><span>, </span><span>88</span><span>]     </span><span># 切片批量改</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>查：in / index / count<a href="#查in--index--count"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>langs </span><span>=</span><span> [</span></span><span>"Python"</span><span>, </span><span>"C++"</span><span>, </span><span>"Java"</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>"Go"</span><span> </span><span>in</span><span> langs)          </span><span># False</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(langs.</span><span>index</span><span>(</span></span><span>"Java"</span><span>))    </span><span># 2（不存在会报 ValueError）</span></div></div><div><div><div>5</div></div><div><span>print</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>2</span><span>, </span><span>3</span><span><span>].</span><span>count</span><span>(</span></span><span>2</span><span>))  </span><span># 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、列表排序<a href="#二列表排序"><span>#</span></a></h2><section><h3>sort 与 sorted 的区别（必考题）<a href="#sort-与-sorted-的区别必考题"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>3</span><span>, </span><span>1</span><span>, </span><span>4</span><span>, </span><span>1</span><span>, </span><span>5</span><span>, </span><span>9</span><span>, </span><span>2</span><span>, </span><span>6</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># sorted()：返回新列表，原列表不动</span></div></div><div><div><div>4</div></div><div><span><span>new </span><span>=</span><span> </span></span><span>sorted</span><span>(nums)</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(new)               </span><span># [1, 1, 2, 3, 4, 5, 6, 9]</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(nums)              </span><span># [3, 1, 4, 1, 5, 9, 2, 6] 原样</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># .sort()：原地排序，返回 None</span></div></div><div><div><div>9</div></div><div><span><span>nums.</span><span>sort</span><span>()</span></span></div></div><div><div><div>10</div></div><div><span>print</span><span>(nums)              </span><span># [1, 1, 2, 3, 4, 5, 6, 9]</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span># 降序</span></div></div><div><div><div>13</div></div><div><span><span>nums.</span><span>sort</span><span>(</span></span><span>reverse</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>14</div></div><div><span>print</span><span>(</span><span>sorted</span><span>(nums, </span><span>reverse</span><span>=</span><span>True</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><code>nums = nums.sort()</code> 是经典错误——sort 返回 None，这句执行后 nums 变成 None。</p></div></div></section><section><h3>按自定义规则排序：key 参数<a href="#按自定义规则排序key-参数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>words </span><span>=</span><span> [</span></span><span>"banana"</span><span>, </span><span>"apple"</span><span>, </span><span>"cherry"</span><span>, </span><span>"fig"</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>words.</span><span>sort</span><span>()                        </span></span><span># 字典序</span></div></div><div><div><div>4</div></div><div><span><span>words.</span><span>sort</span><span>(</span></span><span>key</span><span>=</span><span>len</span><span>)                 </span><span># 按长度：['fig', 'apple', ...]</span></div></div><div><div><div>5</div></div><div><span><span>words.</span><span>sort</span><span>(</span></span><span>key</span><span>=</span><span>len</span><span>, </span><span>reverse</span><span>=</span><span>True</span><span>)   </span><span># 按长度降序</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 排序复杂数据：按成绩降序</span></div></div><div><div><div>8</div></div><div><span><span>students </span><span>=</span><span> [(</span></span><span>"小明"</span><span>, </span><span>90</span><span>), (</span><span>"小红"</span><span>, </span><span>85</span><span>), (</span><span>"小刚"</span><span>, </span><span>92</span><span>)]</span></div></div><div><div><div>9</div></div><div><span><span>students.</span><span>sort</span><span>(</span></span><span>key</span><span>=</span><span>lambda</span><span> </span><span>s</span><span>: s[</span><span>1</span><span>], </span><span>reverse</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(students)     </span><span># [('小刚', 92), ('小明', 90), ('小红', 85)]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>lambda s: s[1]</code> 是匿名函数（第六篇详讲），意思是”取每个元素的第 1 位作为排序依据”。</p></section><section><h3>max / min / sum<a href="#max--min--sum"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>max</span><span>(scores), </span><span>min</span><span>(scores), </span><span>sum</span><span>(scores))</span></div></div><div><div><div>4</div></div><div><span># 92 66 411</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>f</span><span>"平均分 </span><span>{</span><span>sum</span><span><span>(scores)</span><span>/</span></span><span>len</span><span>(scores)</span><span>:.1f</span><span>}</span><span>"</span><span>)   </span><span># 82.2</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、遍历与复制：深浅拷贝的坑<a href="#三遍历与复制深浅拷贝的坑"><span>#</span></a></h2><section><h3>直接赋值 ≠ 复制<a href="#直接赋值--复制"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>b </span><span>=</span><span> a              </span></span><span># 不是复制！b 和 a 指向同一个列表</span></div></div><div><div><div>3</div></div><div><span><span>b.</span><span>append</span><span>(</span></span><span>4</span><span>)</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(a)           </span><span># [1, 2, 3, 4] —— a 也"变"了</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(a </span><span>is</span><span> b)      </span><span># True</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>浅拷贝的三种写法<a href="#浅拷贝的三种写法"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>b </span><span>=</span><span> a.</span><span>copy</span><span>()       </span></span><span># 写法1</span></div></div><div><div><div>3</div></div><div><span><span>c </span><span>=</span><span> a[:]           </span></span><span># 写法2 切片</span></div></div><div><div><div>4</div></div><div><span><span>d </span><span>=</span><span> </span></span><span>list</span><span>(a)        </span><span># 写法3 构造</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>b.</span><span>append</span><span>(</span></span><span>4</span><span>)</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(a)           </span><span># [1, 2, 3] ✓ a 不受影响</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(a </span><span>is</span><span> b)      </span><span># False</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>浅拷贝依然有坑：嵌套结构<a href="#浅拷贝依然有坑嵌套结构"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a </span><span>=</span><span> [</span></span><span>1</span><span>, [</span><span>2</span><span>, </span><span>3</span><span>]]</span></div></div><div><div><div>2</div></div><div><span><span>b </span><span>=</span><span> a.</span><span>copy</span><span>()       </span></span><span># 浅拷贝：只复制第一层</span></div></div><div><div><div>3</div></div><div><span>b[</span><span>1</span><span><span>].</span><span>append</span><span>(</span></span><span>4</span><span>)</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(a)           </span><span># [1, [2, 3, 4]] —— 内层列表是共享的！</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># 深拷贝：彻底独立</span></div></div><div><div><div>7</div></div><div><span>import</span><span> copy</span></div></div><div><div><div>8</div></div><div><span><span>c </span><span>=</span><span> copy.</span><span>deepcopy</span><span>(a)</span></span></div></div><div><div><div>9</div></div><div><span>c[</span><span>1</span><span><span>].</span><span>append</span><span>(</span></span><span>99</span><span>)</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(a)           </span><span># [1, [2, 3, 4]] 不受影响 ✓</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>记忆法</strong>：<code>=</code> 是”贴标签”，<code>.copy()</code> 是”复印一层”，<code>deepcopy</code> 是”整棵复印”。</p></section></section>
<section><h2>四、案例：成绩统计与购物车<a href="#四案例成绩统计与购物车"><span>#</span></a></h2><section><h3>成绩统计<a href="#成绩统计"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>, </span><span>88</span><span>, </span><span>73</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>f</span><span>"人数: </span><span>{</span><span>len</span><span>(scores)</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>f</span><span>"最高: </span><span>{</span><span>max</span><span>(scores)</span><span>}</span><span>  最低: </span><span>{</span><span>min</span><span>(scores)</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>f</span><span>"平均: </span><span>{</span><span>sum</span><span><span>(scores)</span><span>/</span></span><span>len</span><span>(scores)</span><span>:.1f</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 统计各分数段</span></div></div><div><div><div>8</div></div><div><span><span>a </span><span>=</span><span> [s </span></span><span>for</span><span> s </span><span>in</span><span> scores </span><span>if</span><span><span> s </span><span>&gt;=</span><span> </span></span><span>90</span><span>]</span></div></div><div><div><div>9</div></div><div><span><span>b </span><span>=</span><span> [s </span></span><span>for</span><span> s </span><span>in</span><span> scores </span><span>if</span><span> </span><span>80</span><span><span> </span><span>&lt;=</span><span> s </span><span>&lt;</span><span> </span></span><span>90</span><span>]</span></div></div><div><div><div>10</div></div><div><span><span>c </span><span>=</span><span> [s </span></span><span>for</span><span> s </span><span>in</span><span> scores </span><span>if</span><span><span> s </span><span>&lt;</span><span> </span></span><span>60</span><span>]</span></div></div><div><div><div>11</div></div><div><span>print</span><span>(</span><span>f</span><span>"90+ 有 </span><span>{</span><span>len</span><span>(a)</span><span>}</span><span> 人，挂科 </span><span>{</span><span>len</span><span>(c)</span><span>}</span><span> 人"</span><span>)</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 排名（保留原下标）</span></div></div><div><div><div>14</div></div><div><span><span>ranking </span><span>=</span><span> </span></span><span>sorted</span><span>(</span><span>enumerate</span><span>(scores), </span><span>key</span><span>=</span><span>lambda</span><span> </span><span>x</span><span>: x[</span><span>1</span><span>], </span><span>reverse</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>15</div></div><div><span>for</span><span> rank, (idx, s) </span><span>in</span><span> </span><span>enumerate</span><span>(ranking, </span><span>1</span><span>):</span></div></div><div><div><div>16</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"第</span><span>{</span><span>rank</span><span>}</span><span>名：</span><span>{</span><span>s</span><span>}</span><span>分（第</span><span>{</span><span><span>idx</span><span>+</span></span><span>1}</span><span>位同学）"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>购物车<a href="#购物车"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>cart </span><span>=</span><span> []            </span></span><span># [(商品名, 单价, 数量), ...]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>add_item</span><span>(</span><span>name</span><span>,</span><span><span> </span><span>price</span></span><span>,</span><span><span> </span><span>qty</span></span><span>=</span><span>1</span><span>):</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> i, (n, p, q) </span><span>in</span><span> </span><span>enumerate</span><span>(cart):</span></div></div><div><div><div>5</div></div><div><span>        </span><span>if</span><span><span> n </span><span>==</span><span> name:                    </span></span><span># 已存在则加数量</span></div></div><div><div><div>6</div></div><div><span><span>            </span></span><span>cart[i] </span><span>=</span><span> (n, p, q </span><span>+</span><span> qty)</span></div></div><div><div><div>7</div></div><div><span>            </span><span>return</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>cart.</span><span>append</span><span>((name, price, qty))</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>def</span><span> </span><span>checkout</span><span>():</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>total </span><span>=</span><span> </span><span>sum</span><span><span>(p </span><span>*</span><span> q </span></span><span>for</span><span> _, p, q </span><span>in</span><span> cart)</span></div></div><div><div><div>12</div></div><div><span>    </span><span>print</span><span>(</span><span>"---- 账单 ----"</span><span>)</span></div></div><div><div><div>13</div></div><div><span>    </span><span>for</span><span> name, price, qty </span><span>in</span><span> cart:</span></div></div><div><div><div>14</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span> × </span><span>{</span><span>qty</span><span>}</span><span> = ¥</span><span>{</span><span><span>price</span><span>*</span><span>qty</span></span><span>:.2f</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>15</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"合计：¥</span><span>{</span><span>total</span><span>:.2f</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>add_item</span><span>(</span></span><span>"键盘"</span><span>, </span><span>199</span><span>, </span><span>1</span><span>)</span></div></div><div><div><div>18</div></div><div><span><span>add_item</span><span>(</span></span><span>"鼠标"</span><span>, </span><span>89</span><span>, </span><span>2</span><span>)</span></div></div><div><div><div>19</div></div><div><span><span>add_item</span><span>(</span></span><span>"键盘"</span><span>, </span><span>199</span><span>, </span><span>1</span><span>)    </span><span># 再买一把 → 数量变 2</span></div></div><div><div><div>20</div></div><div><span><span>checkout</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>五、元组：不可变的列表<a href="#五元组不可变的列表"><span>#</span></a></h2><section><h3>创建与使用<a href="#创建与使用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>point </span><span>=</span><span> (</span></span><span>3</span><span>, </span><span>5</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>single </span><span>=</span><span> (</span></span><span>42</span><span>,)          </span><span># ⚠️ 单元素必须带逗号！</span></div></div><div><div><div>3</div></div><div><span><span>also_tuple </span><span>=</span><span> </span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>    </span><span># 括号可省，逗号才是本质</span></div></div><div><div><div>4</div></div><div><span><span>x, y </span><span>=</span><span> point            </span></span><span># 解包：x=3, y=5</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(also_tuple)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>元组支持索引、切片、len、in、遍历——<strong>一切”读”操作都与列表相同</strong>；但不能增删改：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>point </span><span>=</span><span> (</span></span><span>3</span><span>, </span><span>5</span><span>)</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(point[</span><span>0</span><span>], </span><span>len</span><span>(point), </span><span>3</span><span> </span><span>in</span><span> point)   </span><span># ✓ 都可以</span></div></div><div><div><div>3</div></div><div><span>point[</span><span>0</span><span><span>] </span><span>=</span><span> </span></span><span>10</span><span>     </span><span># ❌ TypeError</span></div></div><div><div><div>4</div></div><div><span><span>point.</span><span>append</span><span>(</span></span><span>6</span><span>)   </span><span># ❌ 没有这个方法</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>为什么需要元组<a href="#为什么需要元组"><span>#</span></a></h3><ol>
<li><strong>安全</strong>：不希望被修改的数据（坐标、配置、日期）用元组，防止误改</li>
<li><strong>字典键</strong>：列表不可哈希不能做键，元组可以：<code>locations = {(39.9, 116.4): "北京"}</code></li>
<li><strong>函数多返回值</strong>：<code>return x, y</code> 本质就是返回元组</li>
<li><strong>性能</strong>：比列表省内存、创建更快</li>
</ol></section><section><h3>元组与列表互转<a href="#元组与列表互转"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>t </span><span>=</span><span> (</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>lst </span><span>=</span><span> </span></span><span>list</span><span>(t)          </span><span># (1,2,3) → [1,2,3]</span></div></div><div><div><div>3</div></div><div><span><span>back </span><span>=</span><span> </span></span><span>tuple</span><span>(lst)      </span><span># [1,2,3] → (1,2,3)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、列表 vs 元组选择指南<a href="#六列表-vs-元组选择指南"><span>#</span></a></h2>

<table><thead><tr><th>场景</th><th>选择</th></tr></thead><tbody><tr><td>会增删改的数据（待办、消息队列）</td><td>列表</td></tr><tr><td>固定不变的数据（坐标、常量组）</td><td>元组</td></tr><tr><td>需要做字典的键</td><td>元组</td></tr><tr><td>函数返回多个值</td><td>元组（自动）</td></tr></tbody></table></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>合并两个列表并去重排序：<code>[1,3,5]</code> 与 <code>[2,3,6]</code> → <code>[1,2,3,5,6]</code>（提示：set 或 手写）</li>
<li>统计列表中出现次数最多的元素（不用库，提示：count + max）</li>
<li>矩阵转置：<code>[[1,2,3],[4,5,6]]</code> → <code>[[1,4],[2,5],[3,6]]</code>（提示：嵌套推导式）</li>
<li>交换 <code>a = (1, [2, 3])</code> 元组中内层列表的第 0 个元素为 99——会报错吗？（动手验证：元组不可变，但内层列表可以）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>列表增删改查：append/extend、insert、remove/pop/del、index/count</li>
<li>sorted 返回新列表，.sort() 原地排序；key 参数自定义规则</li>
<li><code>=</code> 是引用，<code>.copy()</code> 浅拷贝只复制一层，嵌套结构用 deepcopy</li>
<li>元组不可变但可读；单元素要带逗号；适合做字典键与返回值</li>
<li>容器选型：要改用列表，固定用元组</li>
</ul><p><strong>下一篇</strong>：字典与集合——用键查值的”通讯录”与自动去重的”收纳盒”。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。深浅拷贝的例子请务必亲手跑一遍，坑过一次就记住了。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-05/</id>
      <title type="text">Python 入门教程（五）：字典与集合</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-05/"/>
      <summary type="text">掌握键值对容器字典的增删改查、get 与 setdefault、遍历三件套与嵌套结构，以及集合的去重、交并差运算，附词频统计与通讯录管理完整实战。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>列表用”位置”找数据（<code>nums[0]</code>），但很多时候我们需要用”名字”找数据——学号查成绩、用户名查密码、单词查释义。<strong>字典</strong>就是干这个的；<strong>集合</strong>则是自动去重的数学容器。学完本篇，Python 四大容器（列表/元组/字典/集合）就集齐了。</p></section>
<section><h2>一、字典：键值对映射<a href="#一字典键值对映射"><span>#</span></a></h2><section><h3>创建与基本访问<a href="#创建与基本访问"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 键值对：{键: 值, ...}</span></div></div><div><div><div>2</div></div><div><span><span>student </span><span>=</span><span> {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>"name"</span><span>: </span><span>"小明"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"age"</span><span>: </span><span>18</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"major"</span><span>: </span><span>"计算机科学"</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>"scores"</span><span>: {</span><span>"python"</span><span>: </span><span>90</span><span>, </span><span>"cpp"</span><span>: </span><span>85</span><span>},   </span><span># 字典可以嵌套</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>print</span><span>(student[</span><span>"name"</span><span>])            </span><span># 小明</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(student[</span><span>"scores"</span><span>][</span><span>"python"</span><span>])   </span><span># 90（链式访问嵌套）</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span># 空字典</span></div></div><div><div><div>13</div></div><div><span><span>empty </span><span>=</span><span> {}</span></span></div></div><div><div><div>14</div></div><div><span><span>also_empty </span><span>=</span><span> </span></span><span>dict</span><span>()</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span># dict() 构造</span></div></div><div><div><div>17</div></div><div><span><span>ages </span><span>=</span><span> </span></span><span>dict</span><span>(</span><span>小明</span><span>=</span><span>18</span><span>, </span><span>小红</span><span>=</span><span>17</span><span>)      </span><span># {'小明': 18, '小红': 17}</span></div></div><div><div><div>18</div></div><div><span><span>pairs </span><span>=</span><span> </span></span><span>dict</span><span>([(</span><span>"a"</span><span>, </span><span>1</span><span>), (</span><span>"b"</span><span>, </span><span>2</span><span>)]) </span><span># {'a': 1, 'b': 2}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>键的要求</strong>：必须不可变（字符串/数字/元组可以，列表不行），且唯一（重复定义后者覆盖前者）。</p></section><section><h3>增与改<a href="#增与改"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>user </span><span>=</span><span> {</span></span><span>"name"</span><span>: </span><span>"小明"</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>user[</span><span>"age"</span><span><span>] </span><span>=</span><span> </span></span><span>18</span><span>          </span><span># 键不存在 → 新增</span></div></div><div><div><div>4</div></div><div><span>user[</span><span>"age"</span><span><span>] </span><span>=</span><span> </span></span><span>19</span><span>          </span><span># 键已存在 → 修改</span></div></div><div><div><div>5</div></div><div><span><span>user.</span><span>update</span><span>({</span></span><span>"city"</span><span>: </span><span>"北京"</span><span>, </span><span>"age"</span><span>: </span><span>20</span><span>})   </span><span># 批量增改</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(user)               </span><span># {'name': '小明', 'age': 20, 'city': '北京'}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>查：安全访问三件套<a href="#查安全访问三件套"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>user </span><span>=</span><span> {</span></span><span>"name"</span><span>: </span><span>"小明"</span><span>, </span><span>"age"</span><span>: </span><span>18</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 1. [] 直接访问：键不存在直接报错</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(user[</span><span>"name"</span><span>])          </span><span># 小明</span></div></div><div><div><div>5</div></div><div><span># print(user["email"])       # ❌ KeyError!</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 2. .get()：不存在返回 None（或默认值），推荐</span></div></div><div><div><div>8</div></div><div><span>print</span><span><span>(user.</span><span>get</span><span>(</span></span><span>"email"</span><span>))             </span><span># None</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(user.</span><span>get</span><span>(</span></span><span>"email"</span><span>, </span><span>"未填写"</span><span>))    </span><span># 未填写</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 3. in：先判断再访问</span></div></div><div><div><div>12</div></div><div><span>if</span><span> </span><span>"age"</span><span> </span><span>in</span><span> user:</span></div></div><div><div><div>13</div></div><div><span>    </span><span>print</span><span>(</span><span>"年龄:"</span><span>, user[</span><span>"age"</span><span>])</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Tip</div></div><div><p>日常写法用 <code>.get()</code>；确定键必存在（如自己刚放进去的）才用 <code>[]</code>。</p></div></div></section><section><h3>setdefault：不存在才设置<a href="#setdefault不存在才设置"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>stats </span><span>=</span><span> {}</span></span></div></div><div><div><div>2</div></div><div><span># 统计字符出现次数的优雅写法</span></div></div><div><div><div>3</div></div><div><span>for</span><span> ch </span><span>in</span><span> </span><span>"hello"</span><span>:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>stats.</span><span>setdefault</span><span>(ch, </span><span>0</span><span>)   </span><span># 没有该键就先设为 0</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>stats[ch] </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(stats)     </span><span># {'h': 1, 'e': 1, 'l': 2, 'o': 1}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>删<a href="#删"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>user </span><span>=</span><span> {</span></span><span>"name"</span><span>: </span><span>"小明"</span><span>, </span><span>"age"</span><span>: </span><span>18</span><span>, </span><span>"city"</span><span>: </span><span>"北京"</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>age </span><span>=</span><span> user.</span><span>pop</span><span>(</span></span><span>"age"</span><span>)      </span><span># 删除并返回值：18</span></div></div><div><div><div>4</div></div><div><span>del</span><span> user[</span><span>"city"</span><span>]           </span><span># del 语句删除</span></div></div><div><div><div>5</div></div><div><span><span>user.</span><span>pop</span><span>(</span></span><span>"email"</span><span>, </span><span>None</span><span>)    </span><span># 键不存在不报错（给了默认值）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>last </span><span>=</span><span> user.</span><span>popitem</span><span>()      </span></span><span># 删除并返回最后一个键值对</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(user)                </span><span># {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>遍历三件套<a href="#遍历三件套"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> {</span></span><span>"小明"</span><span>: </span><span>90</span><span>, </span><span>"小红"</span><span>: </span><span>85</span><span>, </span><span>"小刚"</span><span>: </span><span>92</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 遍历键（默认就是遍历键）</span></div></div><div><div><div>4</div></div><div><span>for</span><span> name </span><span>in</span><span> scores:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(name)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 遍历值</span></div></div><div><div><div>8</div></div><div><span>for</span><span> score </span><span>in</span><span><span> scores.</span><span>values</span><span>():</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>print</span><span>(score)</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 同时遍历键和值（最常用）</span></div></div><div><div><div>12</div></div><div><span>for</span><span> name, score </span><span>in</span><span><span> scores.</span><span>items</span><span>():</span></span></div></div><div><div><div>13</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span>: </span><span>{</span><span>score</span><span>}</span><span> 分"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>其他常用操作<a href="#其他常用操作"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> {</span></span><span>"小明"</span><span>: </span><span>90</span><span>, </span><span>"小红"</span><span>: </span><span>85</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>len</span><span>(scores))            </span><span># 2</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>max</span><span>(scores, </span><span>key</span><span><span>=</span><span>scores.get))   </span></span><span># 小刚→最高分的人名（key=按值比较）</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(scores.</span><span>keys</span><span>()))    </span></span><span># ['小明', '小红']</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(scores.</span><span>values</span><span>()))  </span></span><span># [90, 85]</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 合并（Python 3.5+）</span></div></div><div><div><div>9</div></div><div><span><span>extra </span><span>=</span><span> {</span></span><span>"小刚"</span><span>: </span><span>92</span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>all_scores </span><span>=</span><span> {</span><span>**</span><span>scores, </span><span>**</span><span>extra}</span></span></div></div><div><div><div>11</div></div><div><span># Python 3.9+ 更简洁：</span></div></div><div><div><div>12</div></div><div><span><span>all_scores </span><span>=</span><span> scores </span><span>|</span><span> extra</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>案例：词频统计（字典最经典应用）<a href="#案例词频统计字典最经典应用"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>text </span><span>=</span><span> </span></span><span>"""python is simple and python is powerful</span></div></div><div><div><div>2</div></div><div><span>learn python and code python"""</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 方法：setdefault 计数</span></div></div><div><div><div>5</div></div><div><span><span>freq </span><span>=</span><span> {}</span></span></div></div><div><div><div>6</div></div><div><span>for</span><span> word </span><span>in</span><span><span> text.</span><span>split</span><span>():</span></span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>freq.</span><span>setdefault</span><span>(word, </span><span>0</span><span>)</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>freq[word] </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># 按次数降序输出 Top 3</span></div></div><div><div><div>11</div></div><div><span>for</span><span> word, count </span><span>in</span><span> </span><span>sorted</span><span><span>(freq.</span><span>items</span><span>(), </span></span><span>key</span><span>=</span><span>lambda</span><span> </span><span>x</span><span>: x[</span><span>1</span><span>], </span><span>reverse</span><span>=</span><span>True</span><span>)[:</span><span>3</span><span>]:</span></div></div><div><div><div>12</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>word</span><span>}</span><span>: </span><span>{</span><span>count</span><span>}</span><span> 次"</span><span>)</span></div></div><div><div><div>13</div></div><div><span># python: 4 次</span></div></div><div><div><div>14</div></div><div><span># and: 2 次</span></div></div><div><div><div>15</div></div><div><span># is: 2 次</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>案例：通讯录（嵌套字典）<a href="#案例通讯录嵌套字典"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>contacts </span><span>=</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>"小明"</span><span>: {</span><span>"phone"</span><span>: </span><span>"138xxxx"</span><span>, </span><span>"city"</span><span>: </span><span>"北京"</span><span>, </span><span>"tags"</span><span>: [</span><span>"同学"</span><span>, </span><span>"编程组"</span><span>]},</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"小红"</span><span>: {</span><span>"phone"</span><span>: </span><span>"139xxxx"</span><span>, </span><span>"city"</span><span>: </span><span>"上海"</span><span>, </span><span>"tags"</span><span>: [</span><span>"同学"</span><span>]},</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>def</span><span> </span><span>show</span><span>(</span><span>name</span><span>):</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>info </span><span>=</span><span> contacts.</span><span>get</span><span>(name)</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> info </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>9</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"没有 </span><span>{</span><span>name</span><span>}</span><span> 的联系方式"</span><span>)</span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>tags </span><span>=</span><span> </span><span>"/"</span><span><span>.</span><span>join</span><span>(info[</span></span><span>"tags"</span><span>])</span></div></div><div><div><div>12</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>name</span><span>}</span><span>｜</span><span>{</span><span>info[</span><span>'phone'</span><span>]</span><span>}</span><span>｜</span><span>{</span><span>info[</span><span>'city'</span><span>]</span><span>}</span><span>｜标签: </span><span>{</span><span>tags</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>def</span><span> </span><span>search_by_city</span><span>(</span><span>city</span><span>):</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>found </span><span>=</span><span> [n </span><span>for</span><span> n, i </span><span>in</span><span><span> contacts.</span><span>items</span><span>() </span></span><span>if</span><span> i[</span><span>"city"</span><span><span>] </span><span>==</span><span> city]</span></span></div></div><div><div><div>16</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>city</span><span>}</span><span> 的联系人: </span><span>{</span><span>found</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span><span>show</span><span>(</span></span><span>"小明"</span><span>)           </span><span># 小明｜138xxxx｜北京｜标签: 同学/编程组</span></div></div><div><div><div>19</div></div><div><span><span>search_by_city</span><span>(</span></span><span>"上海"</span><span>)  </span><span># 上海 的联系人: ['小红']</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>二、集合：去重与集合运算<a href="#二集合去重与集合运算"><span>#</span></a></h2><section><h3>创建与去重<a href="#创建与去重"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 花括号内是元素（不是键值对）就是集合</span></div></div><div><div><div>2</div></div><div><span><span>fruits </span><span>=</span><span> {</span></span><span>"apple"</span><span>, </span><span>"banana"</span><span>, </span><span>"apple"</span><span>, </span><span>"cherry"</span><span>}</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(fruits)          </span><span># {'apple', 'banana', 'cherry'} 自动去重！</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>len</span><span>(fruits))     </span><span># 3</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># ⚠️ 空花括号是字典不是集合！</span></div></div><div><div><div>7</div></div><div><span><span>empty_dict </span><span>=</span><span> {}</span></span></div></div><div><div><div>8</div></div><div><span><span>empty_set </span><span>=</span><span> </span></span><span>set</span><span>()      </span><span># 空集合必须用 set()</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># 从列表去重（最常用场景）</span></div></div><div><div><div>11</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>3</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>1</span><span>, </span><span>5</span><span>]</span></div></div><div><div><div>12</div></div><div><span><span>unique </span><span>=</span><span> </span></span><span>list</span><span>(</span><span>set</span><span>(nums))</span></div></div><div><div><div>13</div></div><div><span>print</span><span>(unique)          </span><span># [1, 2, 3, 5]（顺序不保证！）</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span># 去重且保序的写法</span></div></div><div><div><div>16</div></div><div><span><span>unique_ordered </span><span>=</span><span> </span></span><span>list</span><span>(</span><span>dict</span><span><span>.</span><span>fromkeys</span><span>(nums))</span></span></div></div><div><div><div>17</div></div><div><span>print</span><span>(unique_ordered)  </span><span># [1, 3, 2, 5] ✓ 保持原序</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>增删<a href="#增删"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>s </span><span>=</span><span> {</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>s.</span><span>add</span><span>(</span></span><span>4</span><span>)          </span><span># 添加单个</span></div></div><div><div><div>4</div></div><div><span><span>s.</span><span>update</span><span>([</span></span><span>5</span><span>, </span><span>6</span><span>])  </span><span># 添加多个</span></div></div><div><div><div>5</div></div><div><span><span>s.</span><span>remove</span><span>(</span></span><span>9</span><span>)       </span><span># ❌ 不存在会 KeyError</span></div></div><div><div><div>6</div></div><div><span><span>s.</span><span>discard</span><span>(</span></span><span>9</span><span>)      </span><span># ✓ 不存在也不报错（推荐）</span></div></div><div><div><div>7</div></div><div><span><span>s.</span><span>pop</span><span>()           </span></span><span># 随机弹出一个元素</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(s)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>集合运算：交并差<a href="#集合运算交并差"><span>#</span></a></h3><p>两个班的选课情况对比：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>class_a </span><span>=</span><span> {</span></span><span>"python"</span><span>, </span><span>"cpp"</span><span>, </span><span>"java"</span><span>, </span><span>"go"</span><span>}</span></div></div><div><div><div>2</div></div><div><span><span>class_b </span><span>=</span><span> {</span></span><span>"python"</span><span>, </span><span>"java"</span><span>, </span><span>"rust"</span><span>, </span><span>"js"</span><span>}</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 交集：都选了的课</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(class_a </span><span>&amp;</span><span> class_b)          </span></span><span># {'python', 'java'}</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(class_a.</span><span>intersection</span><span>(class_b))   </span></span><span># 同上</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 并集：所有人选过的课</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(class_a </span><span>|</span><span> class_b)          </span></span><span># {'python','cpp','java','go','rust','js'}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 差集：A 选了 B 没选的</span></div></div><div><div><div>12</div></div><div><span>print</span><span><span>(class_a </span><span>-</span><span> class_b)          </span></span><span># {'cpp', 'go'}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span># 对称差：只有一方选了的（并集 - 交集）</span></div></div><div><div><div>15</div></div><div><span>print</span><span><span>(class_a </span><span>^</span><span> class_b)          </span></span><span># {'cpp', 'go', 'rust', 'js'}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># 子集与超集</span></div></div><div><div><div>18</div></div><div><span>print</span><span>({</span><span>"python"</span><span><span>} </span><span>&lt;=</span><span> class_a)      </span></span><span># True 子集判断</span></div></div><div><div><div>19</div></div><div><span>print</span><span><span>(class_a.</span><span>issubset</span><span>(class_a </span><span>|</span><span> class_b))   </span></span><span># True</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>助记</strong>：<code>&amp;</code> 交（都有的）、<code>|</code> 并（合起来）、<code>-</code> 差（我有你没有）、<code>^</code> 异（不共有的）。</p></section><section><h3>集合推导式与 frozenset<a href="#集合推导式与-frozenset"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>squares </span><span>=</span><span> {i</span><span>**</span></span><span>2</span><span> </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>1</span><span>, </span><span>6</span><span>)}</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(squares)      </span><span># {1, 4, 9, 16, 25}</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># frozenset：不可变集合，可作为字典键</span></div></div><div><div><div>5</div></div><div><span><span>fs </span><span>=</span><span> </span></span><span>frozenset</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>])</span></div></div><div><div><div>6</div></div><div><span># fs.add(4)         # ❌ 不可变</span></div></div><div><div><div>7</div></div><div><span><span>cache </span><span>=</span><span> {fs: </span></span><span>"结果"</span><span>}   </span><span># ✓ 合法</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>成员测试的性能优势<a href="#成员测试的性能优势"><span>#</span></a></h3><p><code>in</code> 集合是 O(1)，<code>in</code> 列表是 O(n)——数据量大时差距巨大：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> time</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>big_list </span><span>=</span><span> </span></span><span>list</span><span>(</span><span>range</span><span>(</span><span>1_000_000</span><span>))</span></div></div><div><div><div>4</div></div><div><span><span>big_set </span><span>=</span><span> </span></span><span>set</span><span>(big_list)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>t1 </span><span>=</span><span> time.</span><span>time</span><span>()</span></span></div></div><div><div><div>7</div></div><div><span>for</span><span> _ </span><span>in</span><span> </span><span>range</span><span>(</span><span>100</span><span>):</span></div></div><div><div><div>8</div></div><div><span>    </span><span>999_999</span><span> </span><span>in</span><span> big_list</span></div></div><div><div><div>9</div></div><div><span><span>t2 </span><span>=</span><span> time.</span><span>time</span><span>()</span></span></div></div><div><div><div>10</div></div><div><span>for</span><span> _ </span><span>in</span><span> </span><span>range</span><span>(</span><span>100</span><span>):</span></div></div><div><div><div>11</div></div><div><span>    </span><span>999_999</span><span> </span><span>in</span><span> big_set</span></div></div><div><div><div>12</div></div><div><span><span>t3 </span><span>=</span><span> time.</span><span>time</span><span>()</span></span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>print</span><span>(</span><span>f</span><span>"列表查找: </span><span>{</span><span><span>(t2</span><span>-</span><span>t1)</span><span>*</span></span><span>1000</span><span>:.1f</span><span>}</span><span>ms"</span><span>)</span></div></div><div><div><div>15</div></div><div><span>print</span><span>(</span><span>f</span><span>"集合查找: </span><span>{</span><span><span>(t3</span><span>-</span><span>t2)</span><span>*</span></span><span>1000</span><span>:.1f</span><span>}</span><span>ms"</span><span>)   </span><span># 快百倍以上</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>实践建议</strong>：频繁判断”某元素是否在一堆数据里”时，把那堆数据转成集合。</p></section></section>
<section><h2>三、四大容器总对比<a href="#三四大容器总对比"><span>#</span></a></h2>

<table><thead><tr><th>特性</th><th>列表 list</th><th>元组 tuple</th><th>字典 dict</th><th>集合 set</th></tr></thead><tbody><tr><td>符号</td><td><code>[1,2]</code></td><td><code>(1,2)</code></td><td><code>{"k":v}</code></td><td><code>{1,2}</code></td></tr><tr><td>有序</td><td>✓</td><td>✓</td><td>✓（3.7+保序）</td><td>✗</td></tr><tr><td>可变</td><td>✓</td><td>✗</td><td>✓</td><td>✓</td></tr><tr><td>允许重复</td><td>✓</td><td>✓</td><td>键不行</td><td>✗</td></tr><tr><td>典型用途</td><td>序列数据</td><td>固定数据</td><td>映射查找</td><td>去重/集合运算</td></tr><tr><td>查找效率</td><td>O(n)</td><td>O(n)</td><td>O(1) 按键</td><td>O(1)</td></tr></tbody></table><p><strong>选型口诀</strong>：排队用列表、锁死用元组、查名用字典、去重用集合。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>统计一句话中每个汉字出现的次数，按次数降序输出（用字典）</li>
<li>两个班学生名单去重合并：A 班 <code>["a","b","c","d"]</code>、B 班 <code>["c","d","e","f"]</code>，输出所有人都名单与”只在一个班”的人</li>
<li>实现简单的英汉字典：支持查词（不存在提示”未收录”）、添加新词、遍历输出所有词条</li>
<li>用集合推导式生成 1~100 中能被 3 或 5 整除的数的平方集合</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>字典按键存取 O(1)；安全访问用 <code>.get()</code>；计数用 <code>setdefault</code></li>
<li>遍历三件套：<code>keys()</code> / <code>values()</code> / <code>items()</code></li>
<li>合并字典：<code>{**a, **b}</code> 或 3.9+ 的 <code>a | b</code></li>
<li>集合自动去重；<code>&amp; | - ^</code> 四大运算；<code>discard</code> 比 <code>remove</code> 安全</li>
<li>空集合用 <code>set()</code>；频繁成员测试选集合不选列表</li>
<li>四大容器选型口诀：排队列表、锁死元组、查名字典、去重集合</li>
</ul><p><strong>下一篇</strong>：函数——把代码封装成可复用的积木。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。词频统计是面试与实战双高频题，务必独立写一遍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-06/</id>
      <title type="text">Python 入门教程（六）：函数详解</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-06/"/>
      <summary type="text">系统讲解函数的定义与调用、参数全家族（默认/关键字/可变/仅关键字）、*与**解包、返回值、作用域与闭包、lambda 与高阶函数、装饰器入门，附实战重构案例。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>前面所有代码都是”线性剧本”——从上往下一次演完。<strong>函数</strong>让你把一段逻辑打包成”招式”，随叫随到、反复使用。函数是代码复用的最小单元，也是从”写脚本”迈向”写工程”的第一步。</p></section>
<section><h2>一、定义与调用<a href="#一定义与调用"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>greet</span><span>(</span><span>name</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""向指定的人问好"""</span><span>          </span><span># docstring 文档字符串</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"你好，</span><span>{</span><span>name</span><span>}</span><span>！"</span><span>)</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>greet</span><span>(</span></span><span>"小明"</span><span>)        </span><span># 调用：你好，小明！</span></div></div><div><div><div>6</div></div><div><span><span>greet</span><span>(</span></span><span>"小红"</span><span>)        </span><span># 同一段代码，复用无需复制粘贴</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>语法要点</strong>：</p><ul>
<li><code>def 函数名(参数):</code> 定义；<code>函数名(实参)</code> 调用</li>
<li>定义不执行、调用才执行——函数可以定义在调用之前（Python 从上往下读）</li>
<li>三引号 docstring 描述函数用途，<code>help(greet)</code> 可查看</li>
<li>函数名规则：小写+下划线（<code>calc_average</code>），动词开头更佳</li>
</ul></section>
<section><h2>二、参数全家族<a href="#二参数全家族"><span>#</span></a></h2><section><h3>1. 位置参数：按顺序对号入座<a href="#1-位置参数按顺序对号入座"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>introduce</span><span>(</span><span>name</span><span>,</span><span><span> </span><span>age</span></span><span>,</span><span><span> </span><span>major</span></span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"我是</span><span>{</span><span>name</span><span>}</span><span>，</span><span>{</span><span>age</span><span>}</span><span>岁，专业</span><span>{</span><span>major</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>introduce</span><span>(</span></span><span>"小明"</span><span>, </span><span>18</span><span>, </span><span>"计算机"</span><span>)    </span><span># 顺序必须一致</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 关键字参数：指名道姓<a href="#2-关键字参数指名道姓"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>introduce</span><span>(</span></span><span>major</span><span>=</span><span>"计算机"</span><span>, </span><span>name</span><span>=</span><span>"小明"</span><span>, </span><span>age</span><span>=</span><span>18</span><span>)   </span><span># 顺序随意</span></div></div><div><div><div>2</div></div><div><span><span>introduce</span><span>(</span></span><span>"小明"</span><span>, </span><span>major</span><span>=</span><span>"软件工程"</span><span>, </span><span>age</span><span>=</span><span>19</span><span>)        </span><span># 位置在前，关键字在后 ✓</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 默认参数：不传就用默认值<a href="#3-默认参数不传就用默认值"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>greet</span><span>(</span><span>name</span><span>,</span><span><span> </span><span>greeting</span></span><span>=</span><span>"你好"</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>greeting</span><span>}</span><span>，</span><span>{</span><span>name</span><span>}</span><span>！"</span><span>)</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>greet</span><span>(</span></span><span>"小明"</span><span>)                </span><span># 你好，小明！</span></div></div><div><div><div>5</div></div><div><span><span>greet</span><span>(</span></span><span>"Tom"</span><span>, </span><span>"Hello"</span><span>)        </span><span># Hello, Tom!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><strong>默认参数的头号大坑——用可变对象做默认值</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>add_item</span><span>(</span><span>item</span><span>,</span><span><span> </span><span>items</span></span><span>=</span><span>[]</span><span>):      </span><span># ❌ 危险！</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>items.</span><span>append</span><span>(item)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> items</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>print</span><span><span>(</span><span>add_item</span><span>(</span></span><span>1</span><span>))    </span><span># [1]</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(</span><span>add_item</span><span>(</span></span><span>2</span><span>))    </span><span># [1, 2]！！默认列表被"记住"了</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># ✅ 正确姿势</span></div></div><div><div><div>9</div></div><div><span>def</span><span> </span><span>add_item</span><span>(</span><span>item</span><span>,</span><span><span> </span><span>items</span></span><span>=</span><span>None</span><span>):</span></div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span> items </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>items </span><span>=</span><span> []</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>items.</span><span>append</span><span>(item)</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> items</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原因：默认值在函数定义时只创建一次。面试高频题。</p></div></div></section><section><h3>4. 可变参数 *args：接收任意个数<a href="#4-可变参数-args接收任意个数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>total</span><span>(*</span><span>nums</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>type</span><span>(nums))         </span><span># &lt;class 'tuple'&gt; 收进元组</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> </span><span>sum</span><span>(nums)</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>print</span><span><span>(</span><span>total</span><span>(</span></span><span>1</span><span>, </span><span>2</span><span>))            </span><span># 3</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(</span><span>total</span><span>(</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>))   </span><span># 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>5. 关键字可变参数 **kwargs：接收任意关键字参数<a href="#5-关键字可变参数-kwargs接收任意关键字参数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>show_info</span><span>(</span><span>name</span><span>,</span><span> </span><span>**</span><span>extra</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"姓名：</span><span>{</span><span>name</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> k, v </span><span>in</span><span><span> extra.</span><span>items</span><span>():</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"  </span><span>{</span><span>k</span><span>}</span><span>: </span><span>{</span><span>v</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>show_info</span><span>(</span></span><span>"小明"</span><span>, </span><span>age</span><span>=</span><span>18</span><span>, </span><span>city</span><span>=</span><span>"北京"</span><span>, </span><span>major</span><span>=</span><span>"计算机"</span><span>)</span></div></div><div><div><div>7</div></div><div><span># 姓名：小明</span></div></div><div><div><div>8</div></div><div><span>#   age: 18</span></div></div><div><div><div>9</div></div><div><span>#   city: 北京</span></div></div><div><div><div>10</div></div><div><span>#   major: 计算机</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>参数顺序铁律<a href="#参数顺序铁律"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>func</span><span>(</span><span>位置参数</span><span>,</span><span><span> </span><span>默认参数</span></span><span>=</span><span>x</span><span>,</span><span> </span><span>*</span><span>args</span><span>,</span><span> </span><span>**</span><span>kwargs</span><span><span>): </span><span>...</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>即：**普通 → 带默认 → *args → <strong>kwargs</strong>。</p></section><section><h3>* 与 ** 的解包妙用<a href="#-与--的解包妙用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>area</span><span>(</span><span>a</span><span>,</span><span><span> </span><span>b</span></span><span>,</span><span><span> </span><span>c</span></span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span># 海伦公式算三角形面积</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>s </span><span>=</span><span> (a </span><span>+</span><span> b </span><span>+</span><span> c) </span><span>/</span><span> </span><span>2</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span><span> (s</span><span>*</span><span>(s</span><span>-</span><span>a)</span><span>*</span><span>(s</span><span>-</span><span>b)</span><span>*</span><span>(s</span><span>-</span><span>c)) </span><span>**</span><span> </span></span><span>0.5</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>sides </span><span>=</span><span> [</span></span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>]</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(</span><span>area</span><span>(*sides))            </span></span><span># * 把列表拆成三个参数</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>info </span><span>=</span><span> {</span></span><span>"name"</span><span>: </span><span>"小明"</span><span>, </span><span>"age"</span><span>: </span><span>18</span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>greet_info </span><span>=</span><span> </span></span><span>lambda</span><span> **</span><span>kw</span><span>: kw</span></div></div><div><div><div>11</div></div><div><span>print</span><span><span>(</span><span>greet_info</span><span>(**info))      </span></span><span># ** 把字典拆成关键字参数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、返回值<a href="#三返回值"><span>#</span></a></h2><section><h3>return 的规则<a href="#return-的规则"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>is_even</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span><span> n </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> </span><span>True</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>False</span><span>               </span><span># 函数遇 return 立即结束</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># 无 return 或只写 return → 返回 None</span></div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>say_hi</span><span>():</span></div></div><div><div><div>8</div></div><div><span>    </span><span>print</span><span>(</span><span>"hi"</span><span>)</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>result </span><span>=</span><span> </span><span>say_hi</span><span>()</span></span></div></div><div><div><div>11</div></div><div><span>print</span><span>(result)                  </span><span># None</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>返回多个值（本质是元组）<a href="#返回多个值本质是元组"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>min_max</span><span>(</span><span>nums</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>min</span><span>(nums), </span><span>max</span><span>(nums)    </span><span># 打包成元组</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>low, high </span><span>=</span><span> </span><span>min_max</span><span>([</span></span><span>3</span><span>, </span><span>1</span><span>, </span><span>4</span><span>, </span><span>1</span><span>, </span><span>5</span><span>])   </span><span># 解包接收</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(low, high)                        </span><span># 1 5</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>函数与解包配合<a href="#函数与解包配合"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>divide</span><span>(</span><span>a</span><span>,</span><span><span> </span><span>b</span></span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span><span> b </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> </span><span>None</span><span>, </span><span>"除数不能为 0"</span><span>      </span><span># 失败返回错误信息</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span><span> a </span><span>/</span><span> b, </span></span><span>None</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>result, error </span><span>=</span><span> </span><span>divide</span><span>(</span></span><span>10</span><span>, </span><span>2</span><span>)</span></div></div><div><div><div>7</div></div><div><span>if</span><span> error:</span></div></div><div><div><div>8</div></div><div><span>    </span><span>print</span><span>(</span><span>"出错:"</span><span>, error)</span></div></div><div><div><div>9</div></div><div><span>else</span><span>:</span></div></div><div><div><div>10</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"结果: </span><span>{</span><span>result</span><span>}</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、作用域：变量看得见谁<a href="#四作用域变量看得见谁"><span>#</span></a></h2><section><h3>LEGB 规则<a href="#legb-规则"><span>#</span></a></h3><p>Python 查找变量的顺序：<strong>L</strong>ocal（函数内）→ <strong>E</strong>nclosing（外层函数）→ <strong>G</strong>lobal（模块级）→ <strong>B</strong>uilt-in（内置）。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>x </span><span>=</span><span> </span></span><span>10</span><span>                  </span><span># 全局变量</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>outer</span><span>():</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>y </span><span>=</span><span> </span><span>20</span><span>              </span><span># outer 的局部变量</span></div></div><div><div><div>5</div></div><div><span>    </span><span>def</span><span> </span><span>inner</span><span>():</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>z </span><span>=</span><span> </span><span>30</span><span>          </span><span># inner 的局部变量</span></div></div><div><div><div>7</div></div><div><span>        </span><span>print</span><span>(x, y, z)  </span><span># 10 20 30：都能看到（LEGB 逐层向外找）</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>inner</span><span>()</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>outer</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>局部改全局：global（慎用）<a href="#局部改全局global慎用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>count </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>click</span><span>():</span></div></div><div><div><div>4</div></div><div><span>    </span><span>global</span><span> count        </span><span># 声明我要改全局变量</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>count </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>click</span><span>(); </span><span>click</span><span>()</span></span></div></div><div><div><div>8</div></div><div><span>print</span><span>(count)            </span><span># 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Tip</div></div><div><p>需要 <code>global</code> 通常说明设计有问题——更好的做法是通过参数传入、返回值传出。多线程环境 global 是重灾区。</p></div></div></section><section><h3>闭包：外层函数的变量被”记住”<a href="#闭包外层函数的变量被记住"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>make_counter</span><span>():</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>n </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>3</div></div><div><span>    </span><span>def</span><span> </span><span>counter</span><span>():</span></div></div><div><div><div>4</div></div><div><span>        </span><span>nonlocal</span><span> n      </span><span># 声明改的是外层函数的变量（不是全局）</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>n </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> n</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> counter      </span><span># 返回函数本身（不带括号！）</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>c </span><span>=</span><span> </span><span>make_counter</span><span>()</span></span></div></div><div><div><div>10</div></div><div><span>print</span><span><span>(</span><span>c</span><span>(), </span><span>c</span><span>(), </span><span>c</span><span>())    </span></span><span># 1 2 3：n 被 counter 记住了</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>nonlocal</code> 用于修改<strong>外层函数</strong>的变量（<code>global</code> 是改模块级，别混淆）。</p></section></section>
<section><h2>五、lambda 与高阶函数<a href="#五lambda-与高阶函数"><span>#</span></a></h2><section><h3>lambda：一行的小函数<a href="#lambda一行的小函数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># lambda 参数: 表达式</span></div></div><div><div><div>2</div></div><div><span><span>square </span><span>=</span><span> </span></span><span>lambda</span><span> </span><span>x</span><span><span>: x </span><span>**</span><span> </span></span><span>2</span></div></div><div><div><div>3</div></div><div><span>print</span><span><span>(</span><span>square</span><span>(</span></span><span>5</span><span>))         </span><span># 25</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 等价的 def 写法</span></div></div><div><div><div>6</div></div><div><span>def</span><span> </span><span>square</span><span>(</span><span>x</span><span>):</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span><span> x </span><span>**</span><span> </span></span><span>2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>lambda 的定位：<strong>临时、简单、用完即弃</strong>，尤其作为参数传递时：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>students </span><span>=</span><span> [(</span></span><span>"小明"</span><span>, </span><span>90</span><span>), (</span><span>"小红"</span><span>, </span><span>85</span><span>), (</span><span>"小刚"</span><span>, </span><span>92</span><span>)]</span></div></div><div><div><div>2</div></div><div><span><span>students.</span><span>sort</span><span>(</span></span><span>key</span><span>=</span><span>lambda</span><span> </span><span>s</span><span>: s[</span><span>1</span><span>])            </span><span># 按成绩排序</span></div></div><div><div><div>3</div></div><div><span><span>best </span><span>=</span><span> </span></span><span>max</span><span>(students, </span><span>key</span><span>=</span><span>lambda</span><span> </span><span>s</span><span>: s[</span><span>1</span><span>])     </span><span># 成绩最高的</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>复杂逻辑禁止写 lambda——写不下也读不懂，老实用 def。</p></section><section><h3>三大高阶函数<a href="#三大高阶函数"><span>#</span></a></h3><p><strong>函数当参数传</strong>的函数叫高阶函数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># map：逐个变换</span></div></div><div><div><div>4</div></div><div><span><span>squares </span><span>=</span><span> </span></span><span>list</span><span>(</span><span>map</span><span>(</span><span>lambda</span><span> </span><span>x</span><span><span>: x</span><span>**</span></span><span>2</span><span>, nums))</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(squares)          </span><span># [1, 4, 9, 16, 25, 36]</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># filter：按条件筛选</span></div></div><div><div><div>8</div></div><div><span><span>evens </span><span>=</span><span> </span></span><span>list</span><span>(</span><span>filter</span><span>(</span><span>lambda</span><span> </span><span>x</span><span><span>: x </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>, nums))</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(evens)            </span><span># [2, 4, 6]</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># sorted（前面讲过）：带 key 排序</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实际上推导式通常更清晰，map/filter 了解即可：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>squares </span><span>=</span><span> [x</span><span>**</span></span><span>2</span><span> </span><span>for</span><span> x </span><span>in</span><span> nums]          </span><span># 与 map 等价，更 Pythonic</span></div></div><div><div><div>2</div></div><div><span><span>evens </span><span>=</span><span> [x </span></span><span>for</span><span> x </span><span>in</span><span> nums </span><span>if</span><span><span> x </span><span>%</span><span> </span></span><span>2</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span>] </span><span># 与 filter 等价</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>六、递归：函数调用自己<a href="#六递归函数调用自己"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>factorial</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""阶乘：n! = n × (n-1)!"""</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> n </span><span>&lt;=</span><span> </span></span><span>1</span><span>:               </span><span># 基线条件（出口）——必须有！</span></div></div><div><div><div>4</div></div><div><span>        </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span><span> n </span><span>*</span><span> </span><span>factorial</span><span>(n </span><span>-</span><span> </span></span><span>1</span><span>)   </span><span># 递归调用</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>print</span><span><span>(</span><span>factorial</span><span>(</span></span><span>5</span><span>))    </span><span># 120 = 5×4×3×2×1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>递归两要素</strong>：基线条件（何时停）+ 递推关系（如何缩小学）。缺出口就是无限递归，触发 <code>RecursionError</code>（默认上限约 1000 层）。</p><p>经典：斐波那契的递归写法与低效问题——</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>fib</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span><span> n </span><span>&lt;</span><span> </span></span><span>2</span><span>:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> n</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span><span> </span><span>fib</span><span>(n</span><span>-</span></span><span>1</span><span><span>) </span><span>+</span><span> </span><span>fib</span><span>(n</span><span>-</span></span><span>2</span><span>)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>print</span><span><span>(</span><span>fib</span><span>(</span></span><span>10</span><span>))    </span><span># 55（fib(35) 就已经很慢——重复计算爆炸）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>七、装饰器入门（进阶预告）<a href="#七装饰器入门进阶预告"><span>#</span></a></h2><p>装饰器是”给函数套一层壳”的语法，Python 工程必用。看懂下面这个计时器，你就理解了它的工作原理：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> time</span></div></div><div><div><div>2</div></div><div><span>from</span><span> functools </span><span>import</span><span> wraps</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>def</span><span> </span><span>timer</span><span>(</span><span>func</span><span>):</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>@wraps</span><span><span>(</span><span>func</span><span>)</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>def</span><span> </span><span>wrapper</span><span>(*</span><span>args</span><span>,</span><span> </span><span>**</span><span>kwargs</span><span>):</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>start </span><span>=</span><span> time.</span><span>time</span><span>()</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>result </span><span>=</span><span> </span><span>func</span><span>(*args, **kwargs)      </span><span># 调用原函数</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>cost </span><span>=</span><span> (time.</span><span>time</span><span>() </span><span>-</span><span> start) </span><span>*</span><span> </span><span>1000</span></div></div><div><div><div>10</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"[</span><span>{</span><span>func.</span><span>__name__</span><span>}</span><span>] 耗时 </span><span>{</span><span>cost</span><span>:.2f</span><span>}</span><span>ms"</span><span>)</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span> result</span></div></div><div><div><div>12</div></div><div><span>    </span><span>return</span><span> wrapper</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>@timer</span><span>                        </span><span># 等价于 slow_sum = timer(slow_sum)</span></div></div><div><div><div>15</div></div><div><span>def</span><span> </span><span>slow_sum</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>16</div></div><div><span>    </span><span>return</span><span> </span><span>sum</span><span>(</span><span>range</span><span>(n))</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span><span>slow_sum</span><span>(</span></span><span>10_000_000</span><span>)          </span><span># [slow_sum] 耗时 187.35ms</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>@timer</code> 只是个语法糖。装饰器链、带参数的装饰器等进阶内容，等做项目时再深入。</p></section>
<section><h2>八、实战重构：把脚本函数化<a href="#八实战重构把脚本函数化"><span>#</span></a></h2><p><strong>重构前</strong>（线性脚本，无法复用）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>scores </span><span>=</span><span> [</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>total </span><span>=</span><span> </span></span><span>sum</span><span>(scores)</span></div></div><div><div><div>3</div></div><div><span><span>avg </span><span>=</span><span> total </span><span>/</span><span> </span></span><span>len</span><span>(scores)</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>f</span><span>"平均 </span><span>{</span><span>avg</span><span>:.1f</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span><span>above </span><span>=</span><span> [s </span></span><span>for</span><span> s </span><span>in</span><span> scores </span><span>if</span><span><span> s </span><span>&gt;=</span><span> avg]</span></span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>f</span><span>"高于平均: </span><span>{</span><span>above</span><span>}</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>重构后</strong>（函数化，可测试可复用）：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>analyze</span><span>(</span><span>scores</span><span>,</span><span><span> </span><span>precision</span></span><span>=</span><span>1</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""分析成绩：返回统计摘要字典"""</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span> scores:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>return</span><span> </span><span>None</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>avg </span><span>=</span><span> </span><span>sum</span><span><span>(scores) </span><span>/</span><span> </span></span><span>len</span><span>(scores)</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> {</span></div></div><div><div><div>7</div></div><div><span>        </span><span>"count"</span><span>: </span><span>len</span><span>(scores),</span></div></div><div><div><div>8</div></div><div><span>        </span><span>"avg"</span><span>: </span><span>round</span><span>(avg, precision),</span></div></div><div><div><div>9</div></div><div><span>        </span><span>"max"</span><span>: </span><span>max</span><span>(scores),</span></div></div><div><div><div>10</div></div><div><span>        </span><span>"min"</span><span>: </span><span>min</span><span>(scores),</span></div></div><div><div><div>11</div></div><div><span>        </span><span>"above_avg"</span><span>: [s </span><span>for</span><span> s </span><span>in</span><span> scores </span><span>if</span><span><span> s </span><span>&gt;=</span><span> avg],</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>def</span><span> </span><span>report</span><span>(</span><span>data</span><span>):</span></div></div><div><div><div>15</div></div><div><span>    </span><span>"""打印摘要"""</span></div></div><div><div><div>16</div></div><div><span>    </span><span>if</span><span> data </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>17</div></div><div><span>        </span><span>print</span><span>(</span><span>"无数据"</span><span>)</span></div></div><div><div><div>18</div></div><div><span>        </span><span>return</span></div></div><div><div><div>19</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"人数 </span><span>{</span><span>data[</span><span>'count'</span><span>]</span><span>}</span><span>，平均 </span><span>{</span><span>data[</span><span>'avg'</span><span>]</span><span>}</span><span>，"</span></div></div><div><div><div>20</div></div><div><span>          </span><span>f</span><span>"最高 </span><span>{</span><span>data[</span><span>'max'</span><span>]</span><span>}</span><span>，高于平均 </span><span>{</span><span>len</span><span>(data[</span><span>'above_avg'</span><span>])</span><span>}</span><span> 人"</span><span>)</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span><span>report</span><span>(</span><span>analyze</span><span>([</span></span><span>90</span><span>, </span><span>85</span><span>, </span><span>78</span><span>, </span><span>92</span><span>, </span><span>66</span><span>]))</span></div></div><div><div><div>23</div></div><div><span><span>report</span><span>(</span><span>analyze</span><span>([]))            </span></span><span># 无数据</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>函数化三原则</strong>：一个函数做一件事、参数进结果出（少用 global）、起个说清楚的名字。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写 <code>is_prime(n)</code> 判断质数，再用它输出 100 内所有质数（重构第三篇的循环版）</li>
<li>写 <code>apply_twice(func, x)</code>：把 func 应用两次，如 <code>apply_twice(lambda x: x*2, 5)</code> → 20</li>
<li>写可变参数函数 <code>average(*nums)</code>，不传参数时返回 0</li>
<li>用闭包写一个”密码尝试计数器”：每调用一次 <code>try_login()</code> 计数 +1，超过 3 次返回”已锁定”</li>
<li>（选做）给第三篇的猜数字游戏包一个 <code>play()</code> 函数，支持参数”最大范围”与”最多机会”</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>参数顺序：普通 → 默认 → <code>*args</code> → <code>**kwargs</code>；默认参数别用可变对象</li>
<li><code>*</code> 拆序列、<code>**</code> 拆字典；return 多值是元组</li>
<li>LEGB 作用域；改全局用 global、改外层用 nonlocal，但都应少用</li>
<li>lambda 用于临时的 key/短逻辑；map/filter 会被推导式替代</li>
<li>递归 = 基线条件 + 递推；装饰器 = 函数的”包装壳”</li>
<li>工程习惯：单一职责、参数进结果出、好名字</li>
</ul><p><strong>下一篇</strong>：迭代器与生成器——省内存的懒加载艺术。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。默认参数的坑和闭包计数器请亲手复现一遍。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-07/</id>
      <title type="text">Python 入门教程（七）：迭代器与生成器</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-07/"/>
      <summary type="text">理解 for 循环背后的迭代协议、迭代器与可迭代对象的区别、生成器函数与生成器表达式的懒加载、yield 的执行原理、无限序列与管道式数据处理，掌握省内存的 Pythonic 写法。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>你每天都在用 <code>for x in ...</code>，但有没有想过 for 到底是怎么”一个个取出”元素的？这背后是 Python 的<strong>迭代协议</strong>。理解它，你就能用<strong>生成器</strong>写出处理百万行数据也不爆内存的代码——这是 Python 进阶的第一道分水岭。</p></section>
<section><h2>一、for 循环的真相：迭代协议<a href="#一for-循环的真相迭代协议"><span>#</span></a></h2><section><h3>可迭代对象与迭代器<a href="#可迭代对象与迭代器"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> n </span><span>in</span><span> nums:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(n)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这段代码的幕后流程：</p><ol>
<li>Python 对 <code>nums</code> 调用 <code>iter()</code> 拿到一个<strong>迭代器</strong></li>
<li>反复对迭代器调用 <code>next()</code> 取元素</li>
<li>抛出 <code>StopIteration</code> 异常时结束循环</li>
</ol><p>手动模拟一遍：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div><span><span>it </span><span>=</span><span> </span></span><span>iter</span><span>(nums)          </span><span># 列表 → 迭代器</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>next</span><span>(it))          </span><span># 1</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>next</span><span>(it))          </span><span># 2</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>next</span><span>(it))          </span><span># 3</span></div></div><div><div><div>7</div></div><div><span># print(next(it))        # ❌ StopIteration！取完了</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>两个概念</strong>：</p>

<table><thead><tr><th>概念</th><th>说明</th><th>例子</th></tr></thead><tbody><tr><td><strong>可迭代对象 Iterable</strong></td><td>实现了 <code>__iter__</code>，能被 for 遍历</td><td>列表、字符串、字典、文件</td></tr><tr><td><strong>迭代器 Iterator</strong></td><td>实现了 <code>__iter__</code> 和 <code>__next__</code>，能被 next()</td><td><code>iter(列表)</code> 的返回值</td></tr></tbody></table><p>关系：迭代器一定可迭代；可迭代对象要通过 iter() 变成迭代器才能 next()。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> collections.abc </span><span>import</span><span> Iterable, Iterator</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>isinstance</span><span>(nums, Iterable))     </span><span># True</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>isinstance</span><span>(nums, Iterator))     </span><span># False！列表本身不是迭代器</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>isinstance</span><span>(</span><span>iter</span><span>(nums), Iterator))   </span><span># True</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>迭代器是一次性的<a href="#迭代器是一次性的"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>it </span><span>=</span><span> </span></span><span>iter</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>])</span></div></div><div><div><div>2</div></div><div><span>for</span><span> x </span><span>in</span><span> it:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(x, </span><span>end</span><span>=</span><span>" "</span><span>)     </span><span># 1 2 3</span></div></div><div><div><div>4</div></div><div><span>for</span><span> x </span><span>in</span><span> it:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(x, </span><span>end</span><span>=</span><span>" "</span><span>)     </span><span># （空！已耗尽）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>而列表可以反复 for——因为每次 for 都会重新 <code>iter()</code> 出新迭代器。</p></section></section>
<section><h2>二、生成器函数：yield 的魔法<a href="#二生成器函数yield-的魔法"><span>#</span></a></h2><section><h3>从写一个开始<a href="#从写一个开始"><span>#</span></a></h3><p>函数体里出现 <code>yield</code>，它就不再是普通函数，而是<strong>生成器函数</strong>——调用它不执行代码，而是返回一个生成器（一种迭代器）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>count_down</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span>(</span><span>"开始倒数"</span><span>)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>while</span><span><span> n </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>yield</span><span> n          </span><span># 产出 n，在此暂停！</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>n </span><span>-=</span><span> </span><span>1</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>gen </span><span>=</span><span> </span><span>count_down</span><span>(</span></span><span>3</span><span>)</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(gen)               </span><span># &lt;generator object ...&gt; 还没执行！</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>print</span><span>(</span><span>next</span><span>(gen))         </span><span># 打印"开始倒数"，返回 3</span></div></div><div><div><div>11</div></div><div><span>print</span><span>(</span><span>next</span><span>(gen))         </span><span># 2（从暂停处继续）</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(</span><span>next</span><span>(gen))         </span><span># 1</span></div></div><div><div><div>13</div></div><div><span># next(gen)              # ❌ StopIteration</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>yield 与 return 的本质区别</strong>：</p><ul>
<li><code>return</code>：交值、函数终结</li>
<li><code>yield</code>：交值、函数<strong>暂停</strong>，下次 next 从暂停行继续，局部变量全部保留</li>
</ul></section><section><h3>生成器 + for：正常使用姿势<a href="#生成器--for正常使用姿势"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>count_down</span><span>(</span><span>n</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>while</span><span><span> n </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>yield</span><span> n</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>n </span><span>-=</span><span> </span><span>1</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>for</span><span> x </span><span>in</span><span><span> </span><span>count_down</span><span>(</span></span><span>5</span><span>):</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(x, </span><span>end</span><span>=</span><span>" "</span><span>)     </span><span># 5 4 3 2 1</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>三、为什么用生成器：省内存<a href="#三为什么用生成器省内存"><span>#</span></a></h2><section><h3>对比实验<a href="#对比实验"><span>#</span></a></h3><p>生成 1000 万个平方数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 列表：一次性全造好放内存</span></div></div><div><div><div>4</div></div><div><span><span>big_list </span><span>=</span><span> [x</span><span>**</span></span><span>2</span><span> </span><span>for</span><span> x </span><span>in</span><span> </span><span>range</span><span>(</span><span>10_000_000</span><span>)]</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(</span><span>f</span><span>"列表占用: </span><span>{</span><span><span>sys.</span><span>getsizeof</span><span>(big_list)</span><span>/</span></span><span>1024</span><span>/</span><span>1024</span><span>:.0f</span><span>}</span><span> MB"</span><span>)   </span><span># 约 80+ MB</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 生成器：用时才算，只存"当前位置"</span></div></div><div><div><div>8</div></div><div><span><span>big_gen  </span><span>=</span><span> (x</span><span>**</span></span><span>2</span><span> </span><span>for</span><span> x </span><span>in</span><span> </span><span>range</span><span>(</span><span>10_000_000</span><span>))</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(</span><span>f</span><span>"生成器占用: </span><span>{</span><span><span>sys.</span><span>getsizeof</span><span>(big_gen)</span></span><span>}</span><span> 字节"</span><span>)              </span><span># 约 200 字节！</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>生成器表达式</strong>：把列表推导式的 <code>[]</code> 换成 <code>()</code> 即可。数据流”边生成边消费”，内存占用恒定——处理大文件、大数据集的标准姿势。</p></section><section><h3>求和场景实测<a href="#求和场景实测"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 一亿个数求和：列表版可能内存吃紧</span></div></div><div><div><div>2</div></div><div><span><span>total </span><span>=</span><span> </span></span><span>sum</span><span>(x </span><span>for</span><span> x </span><span>in</span><span> </span><span>range</span><span>(</span><span>100_000_000</span><span>))    </span><span># 生成器：平稳跑完</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(total)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、生成器实战模式<a href="#四生成器实战模式"><span>#</span></a></h2><section><h3>1. 无限序列<a href="#1-无限序列"><span>#</span></a></h3><p>生成器不预生成全部，所以能表达”无限”：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>fibonacci</span><span>():</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""无限斐波那契数列"""</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>a, b </span><span>=</span><span> </span><span>0</span><span>, </span><span>1</span></div></div><div><div><div>4</div></div><div><span>    </span><span>while</span><span> </span><span>True</span><span>:            </span><span># 死循环？配合 yield 就是无限流</span></div></div><div><div><div>5</div></div><div><span>        </span><span>yield</span><span> a</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>a, b </span><span>=</span><span> b, a </span><span>+</span><span> b</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 取前 10 个：islice 从无限流切片</span></div></div><div><div><div>9</div></div><div><span>from</span><span> itertools </span><span>import</span><span> islice</span></div></div><div><div><div>10</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>islice</span><span>(</span><span>fibonacci</span><span>(), </span></span><span>10</span><span>)))</span></div></div><div><div><div>11</div></div><div><span># [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 找到第一个大于 1000 的斐波那契数</span></div></div><div><div><div>14</div></div><div><span>for</span><span> f </span><span>in</span><span><span> </span><span>fibonacci</span><span>():</span></span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span><span> f </span><span>&gt;</span><span> </span></span><span>1000</span><span>:</span></div></div><div><div><div>16</div></div><div><span>        </span><span>print</span><span>(f)          </span><span># 1597</span></div></div><div><div><div>17</div></div><div><span>        </span><span>break</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>2. 读大文件（最经典场景）<a href="#2-读大文件最经典场景"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>read_large_file</span><span>(</span><span>path</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""逐行读取大文件，绝不整体载入"""</span></div></div><div><div><div>3</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>for</span><span> line </span><span>in</span><span> f:            </span><span># 文件对象本身可迭代（懒加载）</span></div></div><div><div><div>5</div></div><div><span>            </span><span>yield</span><span><span> line.</span><span>strip</span><span>()</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 统计一个 10GB 日志也只用几 MB 内存</span></div></div><div><div><div>8</div></div><div><span><span>error_count </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>9</div></div><div><span>for</span><span> line </span><span>in</span><span><span> </span><span>read_large_file</span><span>(</span></span><span>"app.log"</span><span>):</span></div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span> </span><span>"ERROR"</span><span> </span><span>in</span><span> line:</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>error_count </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(</span><span>f</span><span>"错误行数: </span><span>{</span><span>error_count</span><span>}</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. 管道式处理（生成器链）<a href="#3-管道式处理生成器链"><span>#</span></a></h3><p>多个生成器串成流水线，数据像水流过每一站：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>lines</span><span>(</span><span>path</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>yield from</span><span> f            </span><span># yield from：把子生成器的值逐个转发</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>def</span><span> </span><span>only_errors</span><span>(</span><span>lines_iter</span><span>):</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> line </span><span>in</span><span> lines_iter:</span></div></div><div><div><div>7</div></div><div><span>        </span><span>if</span><span> </span><span>"ERROR"</span><span> </span><span>in</span><span> line:</span></div></div><div><div><div>8</div></div><div><span>            </span><span>yield</span><span> line</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>def</span><span> </span><span>with_lineno</span><span>(</span><span>lines_iter</span><span>):</span></div></div><div><div><div>11</div></div><div><span>    </span><span>for</span><span> i, line </span><span>in</span><span> </span><span>enumerate</span><span>(lines_iter, </span><span>1</span><span>):</span></div></div><div><div><div>12</div></div><div><span>        </span><span>yield</span><span> </span><span>f</span><span>"行</span><span>{</span><span>i</span><span>}</span><span>: </span><span>{</span><span><span>line.</span><span>rstrip</span><span>()</span></span><span>}</span><span>"</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span># 组装流水线：此刻什么都没发生（全懒）</span></div></div><div><div><div>15</div></div><div><span><span>pipeline </span><span>=</span><span> </span><span>with_lineno</span><span>(</span><span>only_errors</span><span>(</span><span>lines</span><span>(</span></span><span>"app.log"</span><span>)))</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># 消费时数据才逐条流过三层</span></div></div><div><div><div>18</div></div><div><span>for</span><span> item </span><span>in</span><span> pipeline:</span></div></div><div><div><div>19</div></div><div><span>    </span><span>print</span><span>(item)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>yield from iterable</code> 等价于 <code>for x in iterable: yield x</code> 的简写。</p></section><section><h3>4. 生成器实现滑窗<a href="#4-生成器实现滑窗"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>window</span><span>(</span><span>seq</span><span>,</span><span><span> </span><span>size</span></span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""滑动窗口：[1,2,3,4] size=2 → (1,2) (2,3) (3,4)"""</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>len</span><span><span>(seq) </span><span>-</span><span> size </span><span>+</span><span> </span></span><span>1</span><span>):</span></div></div><div><div><div>4</div></div><div><span>        </span><span>yield</span><span> </span><span>tuple</span><span><span>(seq[i:i</span><span>+</span><span>size])</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>window</span><span>([</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>], </span><span>3</span><span>)))</span></div></div><div><div><div>7</div></div><div><span># [(1, 2, 3), (2, 3, 4), (3, 4, 5)]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>五、itertools：迭代器工具箱（标准库）<a href="#五itertools迭代器工具箱标准库"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> itertools </span><span>import</span><span> chain, product, combinations, islice, count</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># chain：拼接多个可迭代对象</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>chain</span><span>([</span></span><span>1</span><span>, </span><span>2</span><span>], </span><span>"ab"</span><span>, (</span><span>3</span><span>,))))      </span><span># [1, 2, 'a', 'b', 3]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># product：笛卡尔积（嵌套循环的扁平写法）</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>product</span><span>(</span></span><span>"AB"</span><span>, </span><span>"12"</span><span>)))</span></div></div><div><div><div>8</div></div><div><span># [('A','1'), ('A','2'), ('B','1'), ('B','2')]</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># combinations：组合（不重复）</span></div></div><div><div><div>11</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>combinations</span><span>([</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>], </span><span>2</span><span>)))     </span><span># [(1,2), (1,3), (2,3)]</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># count：无限计数器</span></div></div><div><div><div>14</div></div><div><span>for</span><span> i </span><span>in</span><span><span> </span><span>count</span><span>(</span></span><span>10</span><span>, </span><span>5</span><span>):      </span><span># 从10开始步进5：10,15,20...</span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span><span> i </span><span>&gt;</span><span> </span></span><span>25</span><span>: </span><span>break</span></div></div><div><div><div>16</div></div><div><span>    </span><span>print</span><span>(i, </span><span>end</span><span>=</span><span>" "</span><span>)       </span><span># 10 15 20 25</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span># islice：给无限流"切片"</span></div></div><div><div><div>19</div></div><div><span>print</span><span>(</span><span>list</span><span><span>(</span><span>islice</span><span>(</span><span>count</span><span>(</span></span><span>1</span><span>, </span><span>2</span><span>), </span><span>5</span><span>)))         </span><span># [1, 3, 5, 7, 9]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>六、自定义迭代器类（预习面向对象）<a href="#六自定义迭代器类预习面向对象"><span>#</span></a></h2><p>给类实现 <code>__iter__</code> 和 <code>__next__</code>，就能被 for 遍历：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Countdown</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>start</span></span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>.n </span><span>=</span><span> start</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>def</span><span> </span><span>__iter__</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span>          </span><span># 自己就是迭代器</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>def</span><span> </span><span>__next__</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>9</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span><span>.n </span><span>&lt;=</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>10</div></div><div><span>            </span><span>raise</span><span> </span><span>StopIteration</span></div></div><div><div><div>11</div></div><div><span>        </span><span>self</span><span><span>.n </span><span>-=</span><span> </span></span><span>1</span></div></div><div><div><div>12</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span><span>.n </span><span>+</span><span> </span></span><span>1</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>for</span><span> x </span><span>in</span><span><span> </span><span>Countdown</span><span>(</span></span><span>3</span><span>):</span></div></div><div><div><div>15</div></div><div><span>    </span><span>print</span><span>(x, </span><span>end</span><span>=</span><span>" "</span><span>)        </span><span># 3 2 1</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>类的语法下一篇详讲，此处先混个脸熟。</p></section>
<section><h2>七、何时用生成器 vs 列表<a href="#七何时用生成器-vs-列表"><span>#</span></a></h2>

<table><thead><tr><th>场景</th><th>选择</th></tr></thead><tbody><tr><td>数据大（文件/百万行）</td><td>生成器</td></tr><tr><td>只遍历一次</td><td>生成器</td></tr><tr><td>需反复遍历 / 下标访问 / len()</td><td>列表</td></tr><tr><td>需要切片、排序完整结果</td><td>列表</td></tr><tr><td>无限/未知长度的流</td><td>只能生成器</td></tr></tbody></table><p><strong>性能口诀</strong>：一次消费用生成，多次使用存列表。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写生成器 <code>running_average(nums)</code>：每接收一个数 yield 当前的平均值</li>
<li>用生成器表达式求 1~1000 中所有素数的平方和（提示：配合第五篇的 is_prime 思路）</li>
<li>写无限生成器 <code>cycle(seq)</code>：<code>cycle("AB")</code> 产出 A B A B…（不许看 itertools 源码）</li>
<li>用管道模式实现：读入一组英文句子 → 只保留含 “python” 的行 → 全部转小写 → 前 5 条（三层生成器链）</li>
<li>（选做）对比 <code>sum([i**2 for i in range(10**7)])</code> 与 <code>sum(i**2 for i in range(10**7))</code> 的内存占用差异（用 <code>sys.getsizeof</code> 或内存监视器）</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>for 的本质：<code>iter()</code> 拿迭代器 → 反复 <code>next()</code> → StopIteration 结束</li>
<li>可迭代 ≠ 迭代器；迭代器是一次性的</li>
<li><code>yield</code> 让函数暂停/恢复；生成器函数调用返回生成器</li>
<li>生成器表达式 <code>(x for x in ...)</code> 惰性求值，内存恒定</li>
<li>四大实战模式：无限序列、大文件、管道链、滑窗</li>
<li>itertools 提供现成工具：chain/product/combinations/islice/count</li>
</ul><p><strong>下一篇</strong>：模块与标准库——站在 Python 自带的”百宝箱”上开发。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。把”管道处理日志”例子跑通，你会对数据流有全新体感。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-08/</id>
      <title type="text">Python 入门教程（八）：模块、包与常用标准库</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-08/"/>
      <summary type="text">掌握模块的导入四种方式与自定义模块、包的结构与 __init__.py、pip 与虚拟环境实战，以及 os/sys/math/random/json/datetime/time/collections 六大高频标准库的用法详解。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>Python 能长期霸榜，一半功劳属于它的<strong>生态</strong>：标准库自带”充电电池”（batteries included），第三方库超过 50 万个。本篇解决三个问题：怎么组织自己的代码（模块与包）、怎么用别人的代码（导入与 pip）、哪些标准库必须先掌握。</p></section>
<section><h2>一、模块：一个 .py 就是一个模块<a href="#一模块一个-py-就是一个模块"><span>#</span></a></h2><section><h3>四种导入方式<a href="#四种导入方式"><span>#</span></a></h3><p>假设有一个 <code>my_utils.py</code>：</p><div><figure><figcaption><span>my_utils.py</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>PI</span><span> </span><span>=</span><span> </span></span><span>3.14159</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>circle_area</span><span>(</span><span>r</span><span>):</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span><span> </span><span>PI</span><span> </span><span>*</span><span> r </span><span>*</span><span> r</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>def</span><span> </span><span>_secret</span><span>():</span></div></div><div><div><div>7</div></div><div><span>    </span><span>"""下划线开头：约定为内部函数，不对外提供"""</span></div></div><div><div><div>8</div></div><div><span>    </span><span>return</span><span> </span><span>"internal"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在其他文件中使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 方式1：导入整个模块（推荐，命名空间清晰）</span></div></div><div><div><div>2</div></div><div><span>import</span><span> my_utils</span></div></div><div><div><div>3</div></div><div><span>print</span><span><span>(my_utils.</span><span>circle_area</span><span>(</span></span><span>2</span><span>))</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 方式2：导入模块并起别名</span></div></div><div><div><div>6</div></div><div><span>import</span><span> my_utils </span><span>as</span><span> mu</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(mu.</span><span>circle_area</span><span>(</span></span><span>2</span><span>))</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># 方式3：导入特定名称（少打字，但可能命名冲突）</span></div></div><div><div><div>10</div></div><div><span>from</span><span> my_utils </span><span>import</span><span><span> circle_area, </span><span>PI</span></span></div></div><div><div><div>11</div></div><div><span>print</span><span><span>(</span><span>circle_area</span><span>(</span></span><span>2</span><span>))</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 方式4：导入全部（不推荐！污染命名空间）</span></div></div><div><div><div>14</div></div><div><span>from</span><span> my_utils </span><span>import</span><span><span> </span><span>*</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><code>from x import *</code> 会引入看不见的名字，还可能覆盖你的变量（如覆盖内置函数）。规范工程禁用。</p></div></div></section><section><h3><code>if __name__ == "__main__"</code>：模块的身份检查<a href="#if-__name__--__main__模块的身份检查"><span>#</span></a></h3><p>每个模块都有魔法属性 <code>__name__</code>：</p><ul>
<li><strong>直接运行</strong>该文件时，<code>__name__</code> 等于 <code>"__main__"</code></li>
<li>被<strong>导入</strong>时，<code>__name__</code> 等于模块名（如 <code>"my_utils"</code>）</li>
</ul><div><figure><figcaption><span>my_utils.py</span></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>circle_area</span><span>(</span><span>r</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span><span> </span><span>PI</span><span> </span><span>*</span><span> r </span><span>*</span><span> r</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>"__main__"</span><span>:</span></div></div><div><div><div>5</div></div><div><span>    </span><span># 这段代码只在直接运行时执行，被导入时不执行</span></div></div><div><div><div>6</div></div><div><span>    </span><span>print</span><span>(</span><span>"自测:"</span><span><span>, </span><span>circle_area</span><span>(</span></span><span>1</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>这是 Python 项目的标准结构</strong>：功能放函数里，测试/演示代码放 main 保护下——既能当库被导入，又能当脚本运行。</p></section><section><h3><code>__all__</code> 控制 <code>import *</code> 的范围<a href="#__all__-控制-import--的范围"><span>#</span></a></h3><div><figure><figcaption><span>my_utils.py</span></figcaption><pre><code><div><div><div>1</div></div><div><span>__all__</span><span><span> </span><span>=</span><span> [</span></span><span>"circle_area"</span><span>, </span><span>"PI"</span><span>]    </span><span># 只导出这两个</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>二、包：目录形式的模块集合<a href="#二包目录形式的模块集合"><span>#</span></a></h2><section><h3>结构<a href="#结构"><span>#</span></a></h3><p>包 = 含 <code>__init__.py</code> 的目录（Python 3.3+ 该文件可省，但保留是好习惯）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>project/</span></div></div><div><div><div>2</div></div><div><span>├── main.py</span></div></div><div><div><div>3</div></div><div><span>└── club/                     # 顶层包</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>├── __init__.py           # 让 club 成为包</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>├── utils.py              # club.utils</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>└── tools/                # 子包</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>├── __init__.py</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>└── net.py            # club.tools.net</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>导入包内模块<a href="#导入包内模块"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> club.utils                      </span><span># 完整路径</span></div></div><div><div><div>2</div></div><div><span><span>club.utils.</span><span>circle_area</span><span>(</span></span><span>2</span><span>)</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>from</span><span> club.tools </span><span>import</span><span> net             </span><span># 从子包导入</span></div></div><div><div><div>5</div></div><div><span>from</span><span> club.tools.net </span><span>import</span><span> ping        </span><span># 导入具体函数</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>import</span><span> club.tools.net </span><span>as</span><span> net           </span><span># 别名</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>绝对导入与相对导入<a href="#绝对导入与相对导入"><span>#</span></a></h3><p>包内部模块互相引用时：</p><div><figure><figcaption><span>club/tools/net.py</span></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> club.utils </span><span>import</span><span> helper      </span><span># 绝对导入（推荐：清晰）</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>from</span><span> ..utils </span><span>import</span><span> helper         </span><span># 相对导入：.. 上一层包</span></div></div><div><div><div>4</div></div><div><span>from</span><span> . </span><span>import</span><span> local_module         </span><span># . 当前包</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>相对导入只能用在包内，脚本顶层文件不可用。</p></section></section>
<section><h2>三、pip 与虚拟环境<a href="#三pip-与虚拟环境"><span>#</span></a></h2><section><h3>pip：第三方包管理器<a href="#pip第三方包管理器"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>requests</span><span>               </span><span># 安装</span></div></div><div><div><div>2</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>requests==</span><span>2.31.0</span><span>       </span><span># 指定版本</span></div></div><div><div><div>3</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>"requests&gt;=2.28"</span><span>       </span><span># 版本范围</span></div></div><div><div><div>4</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>-r</span><span> </span><span>requirements.txt</span><span>    </span><span># 按清单批量安装</span></div></div><div><div><div>5</div></div><div><span>pip</span><span> </span><span>uninstall</span><span> </span><span>requests</span><span>             </span><span># 卸载</span></div></div><div><div><div>6</div></div><div><span>pip</span><span> </span><span>list</span><span>                           </span><span># 已装列表</span></div></div><div><div><div>7</div></div><div><span>pip</span><span> </span><span>show</span><span> </span><span>requests</span><span>                  </span><span># 包详情</span></div></div><div><div><div>8</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>-i</span><span> </span><span>https://pypi.tuna.tsinghua.edu.cn/simple</span><span> </span><span>包名</span><span>   </span><span># 国内镜像加速</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>requirements.txt</strong>：项目依赖清单，交接与部署必备：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip</span><span> </span><span>freeze</span><span> &gt; </span><span>requirements.txt</span><span>      </span><span># 导出当前环境全部依赖</span></div></div><div><div><div>2</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>-r</span><span> </span><span>requirements.txt</span><span>    </span><span># 他人一键还原</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>虚拟环境：项目隔离的结界<a href="#虚拟环境项目隔离的结界"><span>#</span></a></h3><p>不同项目依赖不同版本的库会互相打架，虚拟环境给每个项目独立空间：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 创建（venv 是标准库自带）</span></div></div><div><div><div>2</div></div><div><span>python</span><span> </span><span>-m</span><span> </span><span>venv</span><span> </span><span>venv</span><span>                 </span><span># 在项目目录生成 venv/ 目录</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 激活</span></div></div><div><div><div>5</div></div><div><span>source</span><span> </span><span>venv/bin/activate</span><span>            </span><span># macOS / Linux</span></div></div><div><div><div>6</div></div><div><span>venv\Scripts\activate</span><span>               </span><span># Windows</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 激活后命令行前缀出现 (venv)，此后 pip 装的包只进这个环境</span></div></div><div><div><div>9</div></div><div><span>(</span><span>venv</span><span>) </span><span>pip</span><span> </span><span>install</span><span> </span><span>requests</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 退出</span></div></div><div><div><div>12</div></div><div><span>deactivate</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>铁律</strong>：每个项目一个虚拟环境，<code>venv/</code> 目录加入 <code>.gitignore</code> 不进版本库。</p><div><div><div></div><div>Tip</div></div><div><p>现代替代品 <code>uv</code>（pip + venv 的极速合一）、<code>poetry</code> 也值得了解，但 venv + pip 是基本功，先掌握它。</p></div></div></section></section>
<section><h2>四、六大高频标准库详解<a href="#四六大高频标准库详解"><span>#</span></a></h2><section><h3>1. os：操作系统交互<a href="#1-os操作系统交互"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> os</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 路径操作（最常用）</span></div></div><div><div><div>4</div></div><div><span><span>os.path.</span><span>join</span><span>(</span></span><span>"club"</span><span>, </span><span>"docs"</span><span>, </span><span>"a.md"</span><span>)    </span><span># club/docs/a.md（跨平台拼接）</span></div></div><div><div><div>5</div></div><div><span><span>os.path.</span><span>exists</span><span>(</span></span><span>"/etc/hosts"</span><span>)            </span><span># True 是否存在</span></div></div><div><div><div>6</div></div><div><span><span>os.path.</span><span>isfile</span><span>(</span></span><span>"a.py"</span><span>)                  </span><span># 是否文件</span></div></div><div><div><div>7</div></div><div><span><span>os.path.</span><span>isdir</span><span>(</span></span><span>"club"</span><span>)                   </span><span># 是否目录</span></div></div><div><div><div>8</div></div><div><span><span>os.path.</span><span>basename</span><span>(</span></span><span>"/a/b/c.txt"</span><span>)          </span><span># c.txt</span></div></div><div><div><div>9</div></div><div><span><span>os.path.</span><span>dirname</span><span>(</span></span><span>"/a/b/c.txt"</span><span>)           </span><span># /a/b</span></div></div><div><div><div>10</div></div><div><span><span>os.path.</span><span>splitext</span><span>(</span></span><span>"photo.jpg"</span><span>)           </span><span># ('photo', '.jpg')</span></div></div><div><div><div>11</div></div><div><span><span>os.path.</span><span>getsize</span><span>(</span></span><span>"a.py"</span><span>)                 </span><span># 字节大小</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 目录操作</span></div></div><div><div><div>14</div></div><div><span><span>os.</span><span>getcwd</span><span>()                             </span></span><span># 当前工作目录</span></div></div><div><div><div>15</div></div><div><span><span>os.</span><span>listdir</span><span>(</span></span><span>"."</span><span>)                         </span><span># 列出目录内容</span></div></div><div><div><div>16</div></div><div><span><span>os.</span><span>makedirs</span><span>(</span></span><span>"a/b/c"</span><span>, </span><span>exist_ok</span><span>=</span><span>True</span><span>)     </span><span># 递归建目录（存在不报错）</span></div></div><div><div><div>17</div></div><div><span><span>os.</span><span>remove</span><span>(</span></span><span>"temp.txt"</span><span>)                   </span><span># 删文件</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>跨平台路径推荐用 <code>pathlib</code>（面向对象风格）</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> pathlib </span><span>import</span><span> Path</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>p </span><span>=</span><span> </span><span>Path</span><span>(</span></span><span>"club"</span><span><span>) </span><span>/</span><span> </span></span><span>"docs"</span><span><span> </span><span>/</span><span> </span></span><span>"a.md"</span><span>      </span><span># 用 / 拼路径，优雅</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(p.</span><span>exists</span><span>(), p.suffix)             </span></span><span># True .md</span></div></div><div><div><div>5</div></div><div><span>for</span><span> md </span><span>in</span><span><span> </span><span>Path</span><span>(</span></span><span>"."</span><span><span>).</span><span>glob</span><span>(</span></span><span>"**/*.md"</span><span>):    </span><span># 递归找所有 md</span></div></div><div><div><div>6</div></div><div><span>    </span><span>print</span><span>(md)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. sys：解释器信息<a href="#2-sys解释器信息"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span>(sys.version)              </span><span># Python 版本串</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(sys.platform)             </span><span># darwin / win32 / linux</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(sys.argv)                 </span><span># 命令行参数列表！</span></div></div><div><div><div>6</div></div><div><span><span>sys.</span><span>exit</span><span>(</span></span><span>1</span><span>)                     </span><span># 退出程序（非0=异常退出）</span></div></div><div><div><div>7</div></div><div><span><span>sys.path.</span><span>append</span><span>(</span></span><span>"/my/libs"</span><span>)     </span><span># 追加模块搜索路径</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>命令行参数实战</strong>：</p><div><figure><figcaption><span>args_demo.py</span></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>"__main__"</span><span>:</span></div></div><div><div><div>4</div></div><div><span>    </span><span># python args_demo.py hello 42</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(sys.argv)             </span><span># ['args_demo.py', 'hello', '42']</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>name </span><span>=</span><span> sys.argv[</span><span>1</span><span>] </span><span>if</span><span> </span><span>len</span><span><span>(sys.argv) </span><span>&gt;</span><span> </span></span><span>1</span><span> </span><span>else</span><span> </span><span>"陌生人"</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"你好, </span><span>{</span><span>name</span><span>}</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. math 与 random<a href="#3-math-与-random"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> math</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>print</span><span><span>(math.</span><span>sqrt</span><span>(</span></span><span>16</span><span>))        </span><span># 4.0 平方根</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(math.</span><span>ceil</span><span>(</span></span><span>3.2</span><span>))       </span><span># 4   向上取整</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(math.</span><span>floor</span><span>(</span></span><span>3.8</span><span>))      </span><span># 3   向下取整</span></div></div><div><div><div>6</div></div><div><span>print</span><span>(math.pi, math.e)      </span><span># 3.141592653589793 2.718281828459045</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(math.</span><span>gcd</span><span>(</span></span><span>12</span><span>, </span><span>18</span><span>))     </span><span># 6   最大公约数</span></div></div><div><div><div>8</div></div><div><span>print</span><span><span>(math.</span><span>log</span><span>(math.e))     </span></span><span># 1.0 自然对数</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(math.</span><span>radians</span><span>(</span></span><span>180</span><span>))    </span><span># 3.1415... 角度转弧度</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> random</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>random.</span><span>seed</span><span>(</span></span><span>42</span><span>)                     </span><span># 固定种子：结果可复现</span></div></div><div><div><div>4</div></div><div><span>print</span><span><span>(random.</span><span>random</span><span>())              </span></span><span># 0.639  [0,1) 浮点</span></div></div><div><div><div>5</div></div><div><span>print</span><span><span>(random.</span><span>randint</span><span>(</span></span><span>1</span><span>, </span><span>6</span><span>))         </span><span># 1~6 整数（含两端）——掷骰子</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(random.</span><span>uniform</span><span>(</span></span><span>1.5</span><span>, </span><span>3.5</span><span>))     </span><span># 区间浮点</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>fruits </span><span>=</span><span> [</span></span><span>"苹果"</span><span>, </span><span>"香蕉"</span><span>, </span><span>"橘子"</span><span>]</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(random.</span><span>choice</span><span>(fruits))        </span></span><span># 随机选一个</span></div></div><div><div><div>10</div></div><div><span>print</span><span><span>(random.</span><span>sample</span><span>(fruits, </span></span><span>2</span><span>))     </span><span># 随机选2个（不重复）</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>]</span></div></div><div><div><div>13</div></div><div><span><span>random.</span><span>shuffle</span><span>(nums)                </span></span><span># 原地打乱</span></div></div><div><div><div>14</div></div><div><span>print</span><span>(nums)                         </span><span># 例如 [3, 1, 5, 2, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. json：数据交换格式（前后端/存储必备）<a href="#4-json数据交换格式前后端存储必备"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> json</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>student </span><span>=</span><span> {</span></span><span>"name"</span><span>: </span><span>"小明"</span><span>, </span><span>"age"</span><span>: </span><span>18</span><span>, </span><span>"scores"</span><span>: [</span><span>90</span><span>, </span><span>85</span><span>], </span><span>"vip"</span><span>: </span><span>True</span><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 序列化：Python → JSON 字符串</span></div></div><div><div><div>6</div></div><div><span><span>text </span><span>=</span><span> json.</span><span>dumps</span><span>(student, </span></span><span>ensure_ascii</span><span>=</span><span>False</span><span>, </span><span>indent</span><span>=</span><span>2</span><span>)</span></div></div><div><div><div>7</div></div><div><span>print</span><span>(text)</span></div></div><div><div><div>8</div></div><div><span># {</span></div></div><div><div><div>9</div></div><div><span>#   "name": "小明",</span></div></div><div><div><div>10</div></div><div><span>#   "age": 18, ...</span></div></div><div><div><div>11</div></div><div><span># }</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 反序列化：JSON 字符串 → Python</span></div></div><div><div><div>14</div></div><div><span><span>data </span><span>=</span><span> json.</span><span>loads</span><span>(text)</span></span></div></div><div><div><div>15</div></div><div><span>print</span><span>(data[</span><span>"scores"</span><span>][</span><span>0</span><span>])          </span><span># 90</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># 读写 JSON 文件</span></div></div><div><div><div>18</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"data.json"</span><span>, </span><span>"w"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>json.</span><span>dump</span><span>(student, f, </span><span>ensure_ascii</span><span>=</span><span>False</span><span>, </span><span>indent</span><span>=</span><span>2</span><span>)</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"data.json"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>loaded </span><span>=</span><span> json.</span><span>load</span><span>(f)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>类型对应表</strong>：</p>

<table><thead><tr><th>Python</th><th>JSON</th></tr></thead><tbody><tr><td>dict</td><td>object</td></tr><tr><td>list / tuple</td><td>array</td></tr><tr><td>str</td><td>string</td></tr><tr><td>int / float</td><td>number</td></tr><tr><td>True / False</td><td>true / false</td></tr><tr><td>None</td><td>null</td></tr></tbody></table><p><code>ensure_ascii=False</code> 让中文正常显示，<code>indent=2</code> 美化缩进——两个参数是日常标配。</p></section><section><h3>5. datetime：日期时间<a href="#5-datetime日期时间"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> datetime </span><span>import</span><span> datetime, date, timedelta</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>now </span><span>=</span><span> datetime.</span><span>now</span><span>()</span></span></div></div><div><div><div>4</div></div><div><span>print</span><span>(now)                    </span><span># 2026-10-29 12:00:00.123456</span></div></div><div><div><div>5</div></div><div><span>print</span><span>(now.year, now.month, now.day, now.hour)</span></div></div><div><div><div>6</div></div><div><span>print</span><span><span>(now.</span><span>weekday</span><span>())          </span></span><span># 0=周一 ... 6=周日</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 格式化输出 ↔ 解析</span></div></div><div><div><div>9</div></div><div><span>print</span><span><span>(now.</span><span>strftime</span><span>(</span></span><span>"%Y-%m-</span><span>%d</span><span> %H:%M:%S"</span><span>))    </span><span># 2026-10-29 12:00:00</span></div></div><div><div><div>10</div></div><div><span>print</span><span><span>(now.</span><span>strftime</span><span>(</span></span><span>"%Y年%m月</span><span>%d</span><span>日 %A"</span><span>))       </span><span># 2026年10月29日 Thursday</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>t </span><span>=</span><span> datetime.</span><span>strptime</span><span>(</span></span><span>"2026-10-01 09:00"</span><span>, </span><span>"%Y-%m-</span><span>%d</span><span> %H:%M"</span><span>)</span></div></div><div><div><div>13</div></div><div><span>print</span><span>(t.year)                 </span><span># 2026</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span># 时间差 timedelta</span></div></div><div><div><div>16</div></div><div><span><span>birthday </span><span>=</span><span> </span><span>datetime</span><span>(</span></span><span>2026</span><span>, </span><span>12</span><span>, </span><span>25</span><span>)</span></div></div><div><div><div>17</div></div><div><span><span>delta </span><span>=</span><span> birthday </span><span>-</span><span> now</span></span></div></div><div><div><div>18</div></div><div><span>print</span><span>(</span><span>f</span><span>"还剩 </span><span>{</span><span>delta.days</span><span>}</span><span> 天"</span><span>)</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>three_days_later </span><span>=</span><span> now </span><span>+</span><span> </span><span>timedelta</span><span>(</span></span><span>days</span><span>=</span><span>3</span><span>)</span></div></div><div><div><div>21</div></div><div><span><span>last_hour </span><span>=</span><span> now </span><span>-</span><span> </span><span>timedelta</span><span>(</span></span><span>hours</span><span>=</span><span>1</span><span>)</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span># 常用格式码：%Y年 %m月 %d日 %H时 %M分 %S秒 %A星期 %B月名</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>6. collections：加强版容器<a href="#6-collections加强版容器"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> collections </span><span>import</span><span> Counter, defaultdict, deque</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># Counter：计数器（词频统计一步到位）</span></div></div><div><div><div>4</div></div><div><span><span>words </span><span>=</span><span> </span></span><span>"the quick the lazy the dog"</span><span><span>.</span><span>split</span><span>()</span></span></div></div><div><div><div>5</div></div><div><span><span>c </span><span>=</span><span> </span><span>Counter</span><span>(words)</span></span></div></div><div><div><div>6</div></div><div><span>print</span><span>(c)                    </span><span># Counter({'the': 3, 'quick': 1, ...})</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(c.</span><span>most_common</span><span>(</span></span><span>2</span><span>))     </span><span># [('the', 3), ('quick', 1)]</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># defaultdict：带默认值的字典（告别 KeyError）</span></div></div><div><div><div>10</div></div><div><span><span>groups </span><span>=</span><span> </span><span>defaultdict</span><span>(</span></span><span>list</span><span>)</span></div></div><div><div><div>11</div></div><div><span>for</span><span> name, </span><span>cls</span><span> </span><span>in</span><span> [(</span><span>"小明"</span><span>,</span><span>"A"</span><span>), (</span><span>"小红"</span><span>,</span><span>"B"</span><span>), (</span><span>"小刚"</span><span>,</span><span>"A"</span><span>)]:</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>groups[</span><span>cls</span><span><span>].</span><span>append</span><span>(name)          </span></span><span># 键不存在自动建空列表</span></div></div><div><div><div>13</div></div><div><span>print</span><span>(</span><span>dict</span><span>(groups))        </span><span># {'A': ['小明', '小刚'], 'B': ['小红']}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span># deque：双端队列（头尾操作都是 O(1)，列表头部操作是 O(n)）</span></div></div><div><div><div>16</div></div><div><span><span>dq </span><span>=</span><span> </span><span>deque</span><span>([</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>])</span></div></div><div><div><div>17</div></div><div><span><span>dq.</span><span>appendleft</span><span>(</span></span><span>0</span><span>)           </span><span># deque([0, 1, 2, 3])</span></div></div><div><div><div>18</div></div><div><span><span>dq.</span><span>append</span><span>(</span></span><span>4</span><span>)               </span><span># deque([0, 1, 2, 3, 4])</span></div></div><div><div><div>19</div></div><div><span><span>dq.</span><span>popleft</span><span>()               </span></span><span># 0（当队列用：append 入队，popleft 出队）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>五、组织你自己项目的建议<a href="#五组织你自己项目的建议"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>my_project/</span></div></div><div><div><div>2</div></div><div><span>├── main.py              # 入口：只做调度</span></div></div><div><div><div>3</div></div><div><span>├── config.py            # 配置集中管理</span></div></div><div><div><div>4</div></div><div><span>├── requirements.txt     # 依赖清单</span></div></div><div><div><div>5</div></div><div><span>├── utils/               # 工具包</span></div></div><div><div><div>6</div></div><div><span>│   ├── __init__.py</span></div></div><div><div><div>7</div></div><div><span>│   ├── files.py         # 文件相关函数</span></div></div><div><div><div>8</div></div><div><span>│   └── net.py           # 网络相关函数</span></div></div><div><div><div>9</div></div><div><span>└── tests/               # 测试</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>└── test_utils.py</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>三条军规：<strong>入口薄、功能分文件、依赖写清单</strong>。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写模块 <code>math_extra.py</code>：提供 <code>is_prime</code>、<code>fib_list(n)</code>，带 <code>__main__</code> 自测块；在另一文件导入验证</li>
<li>用 <code>pathlib</code> 递归统计某目录下所有 <code>.py</code> 文件的总行数</li>
<li>用 <code>json</code> 把一个”通讯录字典”保存到文件，重启程序后能加载回来</li>
<li>用 <code>Counter</code> 统计一段英文中出现频率最高的 5 个单词（去掉 the/a/is 等停用词）</li>
<li>（综合）写”倒计时提醒器”：输入目标日期字符串，输出距今还有几天几小时，用 <code>datetime</code> 实现</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>四种导入方式，推荐 <code>import x</code> / <code>import x as y</code>；禁用 <code>import *</code></li>
<li><code>if __name__ == "__main__"</code> 让模块既能导入又能运行</li>
<li>包 = 目录 + <code>__init__.py</code>；一项目一虚拟环境，依赖写 requirements.txt</li>
<li>六大标准库：os(path)/sys(argv)/math/random/json/datetime/collections</li>
<li>路径处理认准 pathlib，词频统计认准 Counter，默认值字典认准 defaultdict</li>
</ul><p><strong>下一篇</strong>：文件操作与异常处理——让程序可靠地读写与容错。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。json 与 datetime 在 Web/爬虫/数据处理的出镜率接近 100%。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-09/</id>
      <title type="text">Python 入门教程（九）：文件操作与异常处理</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-09/"/>
      <summary type="text">完整讲解文件读写模式与 with 上下文管理、编码问题排查、逐行处理与追加写入，异常处理全语法（try/except/else/finally/raise）、自定义异常与工程化容错策略，附日志记录实战。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>程序的价值在于<strong>持久化</strong>（数据存下来）和<strong>健壮性</strong>（出错不崩）。本篇把文件操作与异常处理一次讲透——这两个主题天然是一对：凡是碰文件、网络、用户输入的代码，都必须考虑”出错怎么办”。</p></section>
<section><h2>一、文件操作<a href="#一文件操作"><span>#</span></a></h2><section><h3>打开模式与编码<a href="#打开模式与编码"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>f </span><span>=</span><span> </span></span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>"r"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>常用模式</strong>：</p>

<table><thead><tr><th>模式</th><th>含义</th><th>文件不存在</th><th>文件存在</th></tr></thead><tbody><tr><td><code>"r"</code></td><td>只读（默认）</td><td>❌ 报错</td><td>从头读</td></tr><tr><td><code>"w"</code></td><td>只写</td><td>✅ 创建</td><td><strong>清空重写！</strong></td></tr><tr><td><code>"a"</code></td><td>追加</td><td>✅ 创建</td><td>末尾追加</td></tr><tr><td><code>"x"</code></td><td>独占创建</td><td>❌ 报错</td><td>❌ 报错（防覆盖）</td></tr><tr><td><code>"r+"</code></td><td>读+写</td><td>❌ 报错</td><td>读写均可</td></tr><tr><td><code>"b"</code></td><td>二进制（rb/wb/ab）</td><td>组合使用</td><td>处理图片/音频等</td></tr></tbody></table><p><strong>编码</strong>：永远显式写 <code>encoding="utf-8"</code>。不写的话 Windows 默认 GBK，同一份代码换个系统就读炸——中文乱码/UnicodeDecodeError 十有八九源自这里。</p></section><section><h3>with 语句：自动关闭（标准姿势）<a href="#with-语句自动关闭标准姿势"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># ❌ 手动式：忘了 close，或中途异常导致文件句柄泄漏</span></div></div><div><div><div>2</div></div><div><span><span>f </span><span>=</span><span> </span></span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>content </span><span>=</span><span> f.</span><span>read</span><span>()</span></span></div></div><div><div><div>4</div></div><div><span><span>f.</span><span>close</span><span>()</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span># ✅ with 式：代码块结束自动关闭，异常也会关闭</span></div></div><div><div><div>7</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>content </span><span>=</span><span> f.</span><span>read</span><span>()</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(content)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>读的四种方式<a href="#读的四种方式"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 1. read()：一次读完整个文件（小文件适用）</span></div></div><div><div><div>2</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>text </span><span>=</span><span> f.</span><span>read</span><span>()</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 2. read(n)：读 n 个字符</span></div></div><div><div><div>6</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>head </span><span>=</span><span> f.</span><span>read</span><span>(</span><span>10</span><span>)          </span><span># 前 10 个字符</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span># 3. readline()：每次读一行</span></div></div><div><div><div>10</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>first </span><span>=</span><span> f.</span><span>readline</span><span>()       </span><span># 第一行（含 \n）</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 4. readlines()：读出所有行组成列表</span></div></div><div><div><div>14</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>lines </span><span>=</span><span> f.</span><span>readlines</span><span>()      </span><span># ['第一行\n', '第二行\n', ...]</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># ⭐ 最佳实践：直接迭代文件对象（逐行懒加载，大文件友好）</span></div></div><div><div><div>18</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>19</div></div><div><span>    </span><span>for</span><span> line </span><span>in</span><span> f:</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>process</span><span>(line.</span><span>strip</span><span>())   </span><span># strip 去掉行尾换行符</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>写文件<a href="#写文件"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># w 模式：覆盖写</span></div></div><div><div><div>2</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"out.txt"</span><span>, </span><span>"w"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>f.</span><span>write</span><span>(</span><span>"第一行</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>f.</span><span>write</span><span>(</span><span>"第二行</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>f.</span><span>writelines</span><span>([</span><span>"三</span><span>\n</span><span>"</span><span>, </span><span>"四</span><span>\n</span><span>"</span><span>])    </span><span># 写入字符串列表（不自动加换行！）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># a 模式：追加写（记日志、断点续写）</span></div></div><div><div><div>8</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"log.txt"</span><span>, </span><span>"a"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>f.</span><span>write</span><span>(</span><span>f</span><span>"新的一条记录</span><span>\n</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div></div><div>Warning</div></div><div><p><code>write</code> 不自动换行，要自己加 <code>\n</code>；<code>"w"</code> 模式打开的一瞬间文件就被清空——哪怕你一行都没写。</p></div></div></section><section><h3>文件指针<a href="#文件指针"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>with</span><span> </span><span>open</span><span>(</span><span>"demo.txt"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>print</span><span><span>(f.</span><span>read</span><span>())        </span></span><span># 读完，指针在末尾</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span><span>(f.</span><span>read</span><span>())        </span></span><span># ''（空！指针已在末尾）</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>f.</span><span>seek</span><span>(</span><span>0</span><span>)              </span><span># 指针拨回开头</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span><span>(f.</span><span>read</span><span>())        </span></span><span># 又能读了</span></div></div><div><div><div>6</div></div><div><span>    </span><span>print</span><span><span>(f.</span><span>tell</span><span>())        </span></span><span># 当前指针位置</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>案例：班级成绩管理（CSV 风格）<a href="#案例班级成绩管理csv-风格"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> csv</span></div></div><div><div><div>2</div></div><div><span>from</span><span> pathlib </span><span>import</span><span> Path</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>def</span><span> </span><span>save_students</span><span>(</span><span>students</span><span>,</span><span><span> </span><span>path</span></span><span>=</span><span>"students.csv"</span><span>):</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"""保存：[(姓名, 成绩), ...]"""</span></div></div><div><div><div>6</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>"w"</span><span>, </span><span>newline</span><span>=</span><span>""</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>writer </span><span>=</span><span> csv.</span><span>writer</span><span>(f)</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>writer.</span><span>writerow</span><span>([</span><span>"姓名"</span><span>, </span><span>"成绩"</span><span>])         </span><span># 表头</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>writer.</span><span>writerows</span><span>(students)</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>def</span><span> </span><span>load_students</span><span>(</span><span>path</span><span>=</span><span>"students.csv"</span><span>):</span></div></div><div><div><div>12</div></div><div><span>    </span><span>"""读取，返回列表"""</span></div></div><div><div><div>13</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span><span> </span><span>Path</span><span>(path).</span><span>exists</span><span>():</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>return</span><span> []</span></div></div><div><div><div>15</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>reader </span><span>=</span><span> csv.</span><span>reader</span><span>(f)</span></div></div><div><div><div>17</div></div><div><span>        </span><span>next</span><span>(reader, </span><span>None</span><span>)                        </span><span># 跳过表头</span></div></div><div><div><div>18</div></div><div><span>        </span><span>return</span><span> [(row[</span><span>0</span><span>], </span><span>int</span><span>(row[</span><span>1</span><span>])) </span><span>for</span><span> row </span><span>in</span><span> reader </span><span>if</span><span> row]</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>save_students</span><span>([(</span></span><span>"小明"</span><span>, </span><span>90</span><span>), (</span><span>"小红"</span><span>, </span><span>85</span><span>)])</span></div></div><div><div><div>21</div></div><div><span>print</span><span><span>(</span><span>load_students</span><span>())</span></span></div></div><div><div><div>22</div></div><div><span># [('小明', 90), ('小红', 85)]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>csv</code> 模块自动处理逗号转义与引号，比手动 split 可靠得多；<code>newline=""</code> 是 csv 写入的标准搭配。</p></section></section>
<section><h2>二、异常处理<a href="#二异常处理"><span>#</span></a></h2><section><h3>没有异常处理的 world<a href="#没有异常处理的-world"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>nums </span><span>=</span><span> [</span></span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(nums[</span><span>10</span><span>])          </span><span># IndexError，程序当场去世</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>"这行永远执行不到"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>try / except 基本结构<a href="#try--except-基本结构"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>risky_code</span><span>()</span></div></div><div><div><div>3</div></div><div><span>except</span><span> SomeError:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>handle_it</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>n </span><span>=</span><span> </span><span>int</span><span>(</span><span>input</span><span>(</span><span>"输入一个数："</span><span>))     </span><span># 输入 "abc" 会抛 ValueError</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(</span><span>100</span><span><span> </span><span>/</span><span> n)                     </span></span><span># n=0 会抛 ZeroDivisionError</span></div></div><div><div><div>4</div></div><div><span>except</span><span> </span><span>ValueError</span><span>:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(</span><span>"这不是有效的数字"</span><span>)</span></div></div><div><div><div>6</div></div><div><span>except</span><span> </span><span>ZeroDivisionError</span><span>:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(</span><span>"除数不能为 0"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>捕获异常信息<a href="#捕获异常信息"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>n </span><span>=</span><span> </span><span>int</span><span>(</span><span>"abc"</span><span>)</span></div></div><div><div><div>3</div></div><div><span>except</span><span> </span><span>ValueError</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"错误详情：</span><span>{</span><span>e</span><span>}</span><span>"</span><span>)       </span><span># invalid literal for int() with base 10: 'abc'</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>多异常与兜底<a href="#多异常与兜底"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>data </span><span>=</span><span> </span><span>load_config</span><span>()</span></div></div><div><div><div>3</div></div><div><span>except</span><span> (</span><span>FileNotFoundError</span><span>, </span><span>PermissionError</span><span>):</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>"配置文件读不了，用默认配置"</span><span>)</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>data </span><span>=</span><span> {</span><span>"debug"</span><span>: </span><span>False</span><span>}</span></div></div><div><div><div>6</div></div><div><span>except</span><span> </span><span>Exception</span><span> </span><span>as</span><span> e:            </span><span># 兜底：捕获所有常规异常</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"未知错误: </span><span>{</span><span>e</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>8</div></div><div><span>    </span><span>raise</span><span>                         </span><span># 打印后继续抛出（记日志场景常用）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>工程军规</strong>：</p><ol>
<li><strong>精确捕获</strong>优先——裸 <code>except:</code> 会连 Ctrl+C 的 KeyboardInterrupt 都吞掉，绝对禁止</li>
<li><code>except Exception</code> 只在最外层兜底用</li>
<li>捕获了就要<strong>处理</strong>（降级/默认值/日志），静默 pass 是埋雷</li>
</ol></section><section><h3>else 与 finally<a href="#else-与-finally"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>read_score</span><span>(</span><span>path</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>f </span><span>=</span><span> </span><span>open</span><span>(path, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>except</span><span> </span><span>FileNotFoundError</span><span>:</span></div></div><div><div><div>5</div></div><div><span>        </span><span>print</span><span>(</span><span>"文件不存在"</span><span>)</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>None</span></div></div><div><div><div>7</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>8</div></div><div><span>        </span><span># try 没出错才执行（把"成功逻辑"和"危险代码"分离）</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>score </span><span>=</span><span> </span><span>int</span><span><span>(f.</span><span>read</span><span>())</span></span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>f.</span><span>close</span><span>()</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span> score</span></div></div><div><div><div>12</div></div><div><span>    </span><span>finally</span><span>:</span></div></div><div><div><div>13</div></div><div><span>        </span><span>print</span><span>(</span><span>"无论如何都执行（常用于清理资源）"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>else</code>：try 块<strong>没有发生异常</strong>时执行</li>
<li><code>finally</code>：<strong>无论如何</strong>都执行（成功/失败/return/break），释放资源的最后一道防线</li>
</ul></section><section><h3>raise：主动抛出<a href="#raise主动抛出"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>set_age</span><span>(</span><span>age</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span> </span><span>isinstance</span><span>(age, </span><span>int</span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>raise</span><span> </span><span>TypeError</span><span>(</span><span>"age 必须是整数"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span> </span><span>0</span><span><span> </span><span>&lt;=</span><span> age </span><span>&lt;=</span><span> </span></span><span>150</span><span>:</span></div></div><div><div><div>5</div></div><div><span>        </span><span>raise</span><span> </span><span>ValueError</span><span>(</span><span>f</span><span>"age 越界: </span><span>{</span><span>age</span><span>}</span><span>"</span><span>)   </span><span># 参数校验的标准做法</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> age</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>set_age</span><span>(</span></span><span>"十八"</span><span>)     </span><span># TypeError: age 必须是整数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>异常链与自定义异常<a href="#异常链与自定义异常"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 自定义异常：继承 Exception（命名以 Error 结尾）</span></div></div><div><div><div>2</div></div><div><span>class</span><span><span> </span><span>ConfigError</span><span>(</span></span><span>Exception</span><span>)</span><span>:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"""配置相关错误"""</span></div></div><div><div><div>4</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>key</span></span><span>,</span><span><span> </span><span>msg</span></span><span>=</span><span>""</span><span>):</span></div></div><div><div><div>5</div></div><div><span>        </span><span>super</span><span>().</span><span>__init__</span><span>(</span><span>f</span><span>"配置项 [</span><span>{</span><span>key</span><span>}</span><span>] 出错: </span><span>{</span><span>msg</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>load_config</span><span>(</span><span>key</span><span>):</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>data </span><span>=</span><span> {</span><span>"host"</span><span>: </span><span>"localhost"</span><span>}</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span> key </span><span>not</span><span> </span><span>in</span><span> data:</span></div></div><div><div><div>10</div></div><div><span>        </span><span>raise</span><span><span> </span><span>ConfigError</span><span>(key, </span></span><span>"缺少必填配置"</span><span>)   </span><span># 抛出自定义异常</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>try</span><span>:</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>load_config</span><span>(</span><span>"port"</span><span>)</span></div></div><div><div><div>14</div></div><div><span>except</span><span> ConfigError </span><span>as</span><span> e:</span></div></div><div><div><div>15</div></div><div><span>    </span><span>print</span><span>(e)        </span><span># 配置项 [port] 出错: 缺少必填配置</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>自定义异常的价值：调用方可以精确 catch 你的业务错误，而不是笼统的 Exception。</p></section><section><h3>常见异常速查表<a href="#常见异常速查表"><span>#</span></a></h3>

<table><thead><tr><th>异常</th><th>触发场景</th></tr></thead><tbody><tr><td><code>ValueError</code></td><td>值不合法：<code>int("abc")</code></td></tr><tr><td><code>TypeError</code></td><td>类型错误：<code>"a" + 1</code></td></tr><tr><td><code>IndexError</code></td><td>下标越界：<code>[1,2][5]</code></td></tr><tr><td><code>KeyError</code></td><td>字典键不存在：<code>d["x"]</code></td></tr><tr><td><code>FileNotFoundError</code></td><td>打开不存在的文件</td></tr><tr><td><code>ZeroDivisionError</code></td><td>除以零</td></tr><tr><td><code>AttributeError</code></td><td>属性/方法不存在：<code>"a".push()</code></td></tr><tr><td><code>NameError</code></td><td>变量未定义</td></tr><tr><td><code>ImportError</code></td><td>导入失败（库没装）</td></tr><tr><td><code>RecursionError</code></td><td>递归过深</td></tr></tbody></table></section></section>
<section><h2>三、实战：带日志的健壮读取器<a href="#三实战带日志的健壮读取器"><span>#</span></a></h2><p>综合本篇知识点（with + 精确捕获 + 自定义异常 + logging）：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> logging</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>logging.</span><span>basicConfig</span><span>(</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>filename</span><span>=</span><span>"app.log"</span><span>, </span><span>level</span><span><span>=</span><span>logging.</span><span>INFO</span><span>,</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>format</span><span>=</span><span>"</span><span>%(asctime)s</span><span> [</span><span>%(levelname)s</span><span>] </span><span>%(message)s</span><span>"</span><span>,</span></div></div><div><div><div>6</div></div><div><span>)</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>class</span><span><span> </span><span>DataFormatError</span><span>(</span></span><span>Exception</span><span>)</span><span>:</span></div></div><div><div><div>9</div></div><div><span>    </span><span>pass</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>def</span><span> </span><span>load_numbers</span><span>(</span><span>path</span><span>):</span></div></div><div><div><div>12</div></div><div><span>    </span><span>"""读取每行一个数字的文件，返回 int 列表；格式问题跳行并记日志"""</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>numbers </span><span>=</span><span> []</span></div></div><div><div><div>14</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>15</div></div><div><span>        </span><span>for</span><span> lineno, line </span><span>in</span><span> </span><span>enumerate</span><span>(f, </span><span>1</span><span>):</span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>line </span><span>=</span><span> line.</span><span>strip</span><span>()</span></div></div><div><div><div>17</div></div><div><span>            </span><span>if</span><span> </span><span>not</span><span> line:</span></div></div><div><div><div>18</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>19</div></div><div><span>            </span><span>try</span><span>:</span></div></div><div><div><div>20</div></div><div><span><span>                </span></span><span>numbers.</span><span>append</span><span>(</span><span>int</span><span>(line))</span></div></div><div><div><div>21</div></div><div><span>            </span><span>except</span><span> </span><span>ValueError</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>22</div></div><div><span><span>                </span></span><span>logging.</span><span>warning</span><span>(</span><span>"第</span><span>%d</span><span>行格式错误，已跳过: </span><span>%r</span><span> (</span><span>%s</span><span>)"</span><span>,</span></div></div><div><div><div>23</div></div><div><span><span>                                </span></span><span>lineno, line, e)</span></div></div><div><div><div>24</div></div><div><span>    </span><span>return</span><span> numbers</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span># 运行：合法行全收录，坏行进日志，程序不崩</span></div></div><div><div><div>27</div></div><div><span>print</span><span><span>(</span><span>load_numbers</span><span>(</span></span><span>"numbers.txt"</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这就是生产代码的样子：<strong>预期内的错降级处理，预期外的错明确抛出，全程留痕</strong>。</p></section>
<section><h2>四、EAFP：Python 的容错哲学<a href="#四eafppython-的容错哲学"><span>#</span></a></h2><p>Python 社区推崇 <strong>EAFP</strong>（Easier to Ask Forgiveness than Permission，先斩后奏）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># LBYL：先问许可（先检查再操作——有竞态风险，且啰嗦）</span></div></div><div><div><div>2</div></div><div><span>if</span><span> </span><span>"port"</span><span> </span><span>in</span><span> config:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>port </span><span>=</span><span> config[</span><span>"port"</span><span>]</span></div></div><div><div><div>4</div></div><div><span>else</span><span>:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>port </span><span>=</span><span> </span><span>8080</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># EAFP：直接干，出错再说（Pythonic）</span></div></div><div><div><div>8</div></div><div><span>try</span><span>:</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>port </span><span>=</span><span> config[</span><span>"port"</span><span>]</span></div></div><div><div><div>10</div></div><div><span>except</span><span> </span><span>KeyError</span><span>:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>port </span><span>=</span><span> </span><span>8080</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 当然这个场景还有最简写法（第五篇）：</span></div></div><div><div><div>14</div></div><div><span><span>port </span><span>=</span><span> config.</span><span>get</span><span>(</span></span><span>"port"</span><span>, </span><span>8080</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>写函数 <code>safe_divide(a, b)</code>：除零时返回 None 并打印友好提示</li>
<li>写”通讯录存取器”：<code>save(contacts, path)</code> 存 json、<code>load(path)</code> 读 json；文件不存在返回空字典；json 损坏时给出明确错误并返回空字典</li>
<li>用 <code>try/except</code> 改写第三篇猜数字游戏：输入非数字不崩溃，提示重输</li>
<li>递归扫描目录，统计所有 <code>.log</code> 文件总大小，单文件读取失败时记 warning 继续（OSError）</li>
<li>（选做）给 <code>load_numbers</code> 加功能：支持”数字,标签”格式（如 <code>90,数学</code>），标签非法时跳行</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>with 自动关文件；读写前想清楚 r/w/a 模式；永远显式 <code>encoding="utf-8"</code></li>
<li>大文件逐行迭代 <code>for line in f</code>，不 read() 全量</li>
<li>try/except 精确捕获；else 无错执行；finally 必执行；raise 主动抛</li>
<li>禁裸 except；吞异常必须处理；业务错误用自定义异常类</li>
<li>EAFP：先干再说，是 Python 的方式</li>
</ul><p><strong>下一篇</strong>：面向对象编程——用类搭建大型程序的组织形态。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。把”带日志读取器”读懂改会，你的代码就从”能跑”升级到”可靠”。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-10/</id>
      <title type="text">Python 入门教程（十）：面向对象编程</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-10/"/>
      <summary type="text">从类的定义到完整面向对象：属性与方法、__init__ 与 self、封装与访问控制、继承与 super、方法重写与多态、魔法方法、property 与 dataclass，用图书馆管理系统贯穿全部知识点。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>函数把”动作”打包，<strong>类</strong>把”数据 + 动作”一起打包。面向对象编程（OOP）是组织大型程序的主流范式——游戏里的每个角色、Web 框架里的每个请求对象、AI 库里的每个模型，都是”类的实例”。本篇从零讲透 Python OOP。</p></section>
<section><h2>一、类与实例：图纸与产品<a href="#一类与实例图纸与产品"><span>#</span></a></h2><section><h3>最小类<a href="#最小类"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Student</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""学生类——图纸"""</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>school </span><span>=</span><span> </span><span>"Cyber先锋社"</span><span>        </span><span># 类属性：所有实例共享</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>age</span></span><span>):    </span><span># 构造方法：创建实例时自动调用</span></div></div><div><div><div>6</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name              </span></span><span># 实例属性：每个实例独有</span></div></div><div><div><div>7</div></div><div><span>        </span><span>self</span><span><span>.age </span><span>=</span><span> age</span></span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>def</span><span> </span><span>introduce</span><span>(</span><span>self</span><span>):              </span><span># 实例方法</span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"我是</span><span>{</span><span>name</span><span>}</span><span>..."</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>核心概念对照</strong>：</p>

<table><thead><tr><th>概念</th><th>类比</th><th>归属</th></tr></thead><tbody><tr><td>类 class</td><td>图纸</td><td>一份</td></tr><tr><td>实例 instance</td><td>按图纸造的产品</td><td>可以很多个</td></tr><tr><td>类属性</td><td>产品系列共同配置</td><td>所有实例共享</td></tr><tr><td>实例属性</td><td>单个产品的编号</td><td>各自独立</td></tr></tbody></table></section><section><h3>创建与使用<a href="#创建与使用"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Student</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>school </span><span>=</span><span> </span><span>"Cyber先锋社"</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>age</span></span><span>):</span></div></div><div><div><div>5</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name</span></span></div></div><div><div><div>6</div></div><div><span>        </span><span>self</span><span><span>.age </span><span>=</span><span> age</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>def</span><span> </span><span>introduce</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>9</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"我是</span><span>{</span><span>self</span><span>.name</span><span>}</span><span>，</span><span>{</span><span>self</span><span>.age</span><span>}</span><span>岁，来自</span><span>{</span><span>self</span><span>.school</span><span>}</span><span>"</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>ming </span><span>=</span><span> </span><span>Student</span><span>(</span></span><span>"小明"</span><span>, </span><span>18</span><span>)          </span><span># 自动调用 __init__</span></div></div><div><div><div>12</div></div><div><span><span>hong </span><span>=</span><span> </span><span>Student</span><span>(</span></span><span>"小红"</span><span>, </span><span>17</span><span>)</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>print</span><span><span>(ming.</span><span>introduce</span><span>())     </span></span><span># 我是小明，18岁，来自Cyber先锋社</span></div></div><div><div><div>15</div></div><div><span>print</span><span><span>(hong.</span><span>introduce</span><span>())     </span></span><span># 我是小红，17岁，来自Cyber先锋社</span></div></div><div><div><div>16</div></div><div><span>print</span><span>(ming.name)            </span><span># 直接访问属性</span></div></div><div><div><div>17</div></div><div><span>print</span><span>(Student.school)       </span><span># 类属性通过类访问</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>self 到底是什么<a href="#self-到底是什么"><span>#</span></a></h3><p><code>self</code> 就是<strong>实例自己</strong>。<code>ming.introduce()</code> 实际是 <code>Student.introduce(ming)</code> 的语法糖——Python 把实例自动传给第一个参数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span><span>(Student.</span><span>introduce</span><span>(ming))    </span></span><span># 与 ming.introduce() 完全等价</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>三条铁律</strong>：实例方法第一个参数必须是 self（名字可换但别换）；调用时不传 self；<code>self.xxx = 值</code> 创建实例属性。</p></section><section><h3>类属性 vs 实例属性的坑<a href="#类属性-vs-实例属性的坑"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Student</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>school </span><span>=</span><span> </span><span>"先锋社"</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>s1 </span><span>=</span><span> </span><span>Student</span><span>()</span></span></div></div><div><div><div>5</div></div><div><span><span>s2 </span><span>=</span><span> </span><span>Student</span><span>()</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>s1.school </span><span>=</span><span> </span></span><span>"吉他社"</span><span>        </span><span># 给 s1 创建了同名实例属性（遮蔽类属性）</span></div></div><div><div><div>8</div></div><div><span>print</span><span>(s1.school)            </span><span># 吉他社（实例属性优先）</span></div></div><div><div><div>9</div></div><div><span>print</span><span>(s2.school)            </span><span># 先锋社（s2 没有实例属性，找到类属性）</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>Student.school </span><span>=</span><span> </span></span><span>"篮球社"</span><span>   </span><span># 改类属性本身</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(s2.school)            </span><span># 篮球社</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>查找顺序</strong>：实例属性 → 类属性 → 父类属性。</p></section><section><h3>实例方法 / 类方法 / 静态方法<a href="#实例方法--类方法--静态方法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> datetime </span><span>import</span><span> date</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>class</span><span><span> </span><span>Student</span></span><span>:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>school </span><span>=</span><span> </span><span>"先锋社"</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>birth_year</span></span><span>):</span></div></div><div><div><div>7</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name</span></span></div></div><div><div><div>8</div></div><div><span>        </span><span>self</span><span><span>.birth_year </span><span>=</span><span> birth_year</span></span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>def</span><span> </span><span>grade</span><span>(</span><span>self</span><span>):                        </span><span># 实例方法：访问实例数据</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span><span> date.</span><span>today</span><span>().year </span><span>-</span><span> </span></span><span>self</span><span>.birth_year</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>@</span><span>classmethod</span></div></div><div><div><div>14</div></div><div><span>    </span><span>def</span><span> </span><span>from_birth_year</span><span>(</span><span>cls</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>age</span></span><span>):    </span><span># 类方法：备选构造器（常用！）</span></div></div><div><div><div>15</div></div><div><span>        </span><span>return</span><span> </span><span>cls</span><span><span>(name, date.</span><span>today</span><span>().year </span><span>-</span><span> age)</span></span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>@</span><span>staticmethod</span></div></div><div><div><div>18</div></div><div><span>    </span><span>def</span><span> </span><span>is_valid_age</span><span>(</span><span>age</span><span>):                  </span><span># 静态方法：与实例无关的工具函数</span></div></div><div><div><div>19</div></div><div><span>        </span><span>return</span><span> </span><span>6</span><span><span> </span><span>&lt;=</span><span> age </span><span>&lt;=</span><span> </span></span><span>100</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span><span>ming </span><span>=</span><span> Student.</span><span>from_birth_year</span><span>(</span></span><span>"小明"</span><span>, </span><span>18</span><span>)   </span><span># 类方法创建实例</span></div></div><div><div><div>22</div></div><div><span>print</span><span><span>(Student.</span><span>is_valid_age</span><span>(ming.</span><span>grade</span><span>()))   </span></span><span># True</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>实例方法：第一个参数 <code>self</code></li>
<li>类方法 <code>@classmethod</code>：第一个参数 <code>cls</code>，常用于<strong>备选构造方式</strong></li>
<li>静态方法 <code>@staticmethod</code>：不带自动参数，就是放在类里的普通函数</li>
</ul></section></section>
<section><h2>二、封装：藏好内部实现<a href="#二封装藏好内部实现"><span>#</span></a></h2><section><h3>下划线约定<a href="#下划线约定"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Account</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>owner</span></span><span>,</span><span><span> </span><span>balance</span></span><span>=</span><span>0</span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>.owner </span><span>=</span><span> owner          </span></span><span># 公开：随意访问</span></div></div><div><div><div>4</div></div><div><span>        </span><span>self</span><span><span>._bank_no </span><span>=</span><span> </span></span><span>"6222..."</span><span>   </span><span># 单下划线：约定为"内部"，外部别碰（语言不禁止）</span></div></div><div><div><div>5</div></div><div><span>        </span><span>self</span><span><span>.__password </span><span>=</span><span> </span></span><span>"123456"</span><span>  </span><span># 双下划线：名称改写，外部无法直接访问</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>def</span><span> </span><span>verify</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>pwd</span></span><span>):</span></div></div><div><div><div>8</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span><span>.</span><span>__check</span><span>(pwd)    </span></span><span># 内部方法公开调用</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>def</span><span> </span><span>__check</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>pwd</span></span><span>):         </span><span># 私有方法</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span><span> pwd </span><span>==</span><span> </span></span><span>self</span><span>.__password</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>acc </span><span>=</span><span> </span><span>Account</span><span>(</span></span><span>"小明"</span><span>)</span></div></div><div><div><div>14</div></div><div><span># print(acc.__password)    # ❌ AttributeError</span></div></div><div><div><div>15</div></div><div><span># print(acc.__check("123"))  # ❌ 同理</span></div></div><div><div><div>16</div></div><div><span>print</span><span><span>(acc.</span><span>verify</span><span>(</span></span><span>"123456"</span><span>))    </span><span># True：通过公开接口使用内部实现</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Python 的私有是”君子协定”：<code>__name</code> 被改写为 <code>_Account__name</code>（用 <code>acc._Account__password</code> 其实能访问到，但永远别这么干）。</p></section><section><h3>property：像属性一样调用的方法<a href="#property像属性一样调用的方法"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Circle</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>radius</span></span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>._radius </span><span>=</span><span> radius</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>@</span><span>property</span></div></div><div><div><div>6</div></div><div><span>    </span><span>def</span><span> </span><span>radius</span><span>(</span><span>self</span><span>):              </span><span># getter：c.radius 触发</span></div></div><div><div><div>7</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span>._radius</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>    </span></span><span><span>@radius</span><span>.</span><span>setter</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>def</span><span> </span><span>radius</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>value</span></span><span>):       </span><span># setter：c.radius = x 触发（带校验）</span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span><span> value </span><span>&lt;=</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>12</div></div><div><span>            </span><span>raise</span><span> </span><span>ValueError</span><span>(</span><span>"半径必须为正数"</span><span>)</span></div></div><div><div><div>13</div></div><div><span>        </span><span>self</span><span><span>._radius </span><span>=</span><span> value</span></span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>@</span><span>property</span></div></div><div><div><div>16</div></div><div><span>    </span><span>def</span><span> </span><span>area</span><span>(</span><span>self</span><span>):                </span><span># 只读属性：只提供 getter</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span> </span><span>3.14159</span><span><span> </span><span>*</span><span> </span></span><span>self</span><span><span>._radius </span><span>**</span><span> </span></span><span>2</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>c </span><span>=</span><span> </span><span>Circle</span><span>(</span></span><span>5</span><span>)</span></div></div><div><div><div>20</div></div><div><span>print</span><span>(c.area)          </span><span># 78.53975 —— 像属性，实际在计算</span></div></div><div><div><div>21</div></div><div><span><span>c.radius </span><span>=</span><span> </span></span><span>10</span><span>          </span><span># 走 setter 校验</span></div></div><div><div><div>22</div></div><div><span>print</span><span>(c.area)          </span><span># 314.159</span></div></div><div><div><div>23</div></div><div><span># c.area = 100         # ❌ AttributeError 只读</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>使用时机</strong>：属性需要计算（面积）或赋值需要校验（半径）时，对外仍保持 <code>obj.attr</code> 的简洁语法。</p></section></section>
<section><h2>三、继承与多态<a href="#三继承与多态"><span>#</span></a></h2><section><h3>继承：代码复用<a href="#继承代码复用"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Animal</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>def</span><span> </span><span>speak</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"</span><span>{</span><span>self</span><span>.name</span><span>}</span><span>在发出声音"</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>    </span><span>def</span><span> </span><span>info</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>9</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"[</span><span>{</span><span>type</span><span>(</span><span>self</span><span>).</span><span>__name__</span><span>}</span><span>] </span><span>{</span><span>self</span><span>.name</span><span>}</span><span>"</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>class</span><span><span> </span><span>Dog</span><span>(</span><span>Animal</span><span>)</span></span><span>:                     </span><span># Dog 继承 Animal</span></div></div><div><div><div>12</div></div><div><span>    </span><span>def</span><span> </span><span>fetch</span><span>(</span><span>self</span><span>):                   </span><span># 子类新增方法</span></div></div><div><div><div>13</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"</span><span>{</span><span>self</span><span>.name</span><span>}</span><span>去捡球！"</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>class</span><span><span> </span><span>Cat</span><span>(</span><span>Animal</span><span>)</span></span><span>:</span></div></div><div><div><div>16</div></div><div><span>    </span><span>def</span><span> </span><span>speak</span><span>(</span><span>self</span><span>):                   </span><span># 方法重写（override）</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"</span><span>{</span><span>self</span><span>.name</span><span>}</span><span>：喵～"</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>dog </span><span>=</span><span> </span><span>Dog</span><span>(</span></span><span>"旺财"</span><span>)</span></div></div><div><div><div>20</div></div><div><span><span>cat </span><span>=</span><span> </span><span>Cat</span><span>(</span></span><span>"咪咪"</span><span>)</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>print</span><span><span>(dog.</span><span>info</span><span>())        </span></span><span># [Dog] 旺财（继承来的方法）</span></div></div><div><div><div>23</div></div><div><span>print</span><span><span>(dog.</span><span>fetch</span><span>())       </span></span><span># 旺财去捡球！（自己的新方法）</span></div></div><div><div><div>24</div></div><div><span>print</span><span><span>(dog.</span><span>speak</span><span>())       </span></span><span># 旺财在发出声音（没重写，用父类版）</span></div></div><div><div><div>25</div></div><div><span>print</span><span><span>(cat.</span><span>speak</span><span>())       </span></span><span># 咪咪：喵～（重写了自己的版本）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>super()：调用父类<a href="#super调用父类"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Animal</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>age</span></span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>self</span><span><span>.age </span><span>=</span><span> age</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>class</span><span><span> </span><span>Dog</span><span>(</span><span>Animal</span><span>)</span></span><span>:</span></div></div><div><div><div>7</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>,</span><span><span> </span><span>age</span></span><span>,</span><span><span> </span><span>breed</span></span><span>):</span></div></div><div><div><div>8</div></div><div><span>        </span><span>super</span><span>().</span><span>__init__</span><span>(name, age)    </span><span># 先让父类完成初始化</span></div></div><div><div><div>9</div></div><div><span>        </span><span>self</span><span><span>.breed </span><span>=</span><span> breed             </span></span><span># 再补充子类特有的</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>d </span><span>=</span><span> </span><span>Dog</span><span>(</span></span><span>"旺财"</span><span>, </span><span>3</span><span>, </span><span>"柴犬"</span><span>)</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(d.name, d.age, d.breed)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>多态：同一接口，不同行为<a href="#多态同一接口不同行为"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>let_it_speak</span><span>(</span><span>animal</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"""不关心具体类型，只管调用 speak——多态的威力"""</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span><span>(animal.</span><span>speak</span><span>())</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>animals </span><span>=</span><span> [</span><span>Dog</span><span>(</span></span><span>"旺财"</span><span><span>), </span><span>Cat</span><span>(</span></span><span>"咪咪"</span><span><span>), </span><span>Animal</span><span>(</span></span><span>"神秘生物"</span><span>)]</span></div></div><div><div><div>6</div></div><div><span>for</span><span> a </span><span>in</span><span> animals:</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>let_it_speak</span><span>(a)</span></div></div><div><div><div>8</div></div><div><span># 旺财在发出声音</span></div></div><div><div><div>9</div></div><div><span># 咪咪：喵～</span></div></div><div><div><div>10</div></div><div><span># 神秘生物在发出声音</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>let_it_speak</code> 对”任何有 speak 方法的对象”都有效——这叫<strong>鸭子类型</strong>（走起来像鸭子叫起来像鸭子，那就是鸭子）。Python 不检查继承关系，只看”有没有这个方法”：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Robot</span></span><span>:                </span><span># 没继承 Animal！</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>speak</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>return</span><span> </span><span>"嘀嘀——"</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>let_it_speak</span><span>(</span><span>Robot</span><span>())       </span></span><span># ✓ 照样工作</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>继承层次检查<a href="#继承层次检查"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>print</span><span>(</span><span>isinstance</span><span>(dog, Dog))       </span><span># True</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(</span><span>isinstance</span><span>(dog, Animal))    </span><span># True（Dog 是 Animal 的子类）</span></div></div><div><div><div>3</div></div><div><span>print</span><span>(</span><span>issubclass</span><span>(Dog, Animal))    </span><span># True</span></div></div><div><div><div>4</div></div><div><span>print</span><span>(</span><span>issubclass</span><span>(Cat, Dog))       </span><span># False</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>四、魔法方法：给类装上”系统接口”<a href="#四魔法方法给类装上系统接口"><span>#</span></a></h2><p>双下划线包裹的方法在特定场景被 Python 自动调用：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span><span> </span><span>Book</span></span><span>:</span></div></div><div><div><div>2</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>title</span></span><span>,</span><span><span> </span><span>price</span></span><span>):</span></div></div><div><div><div>3</div></div><div><span>        </span><span>self</span><span><span>.title </span><span>=</span><span> title</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>self</span><span><span>.price </span><span>=</span><span> price</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>def</span><span> </span><span>__str__</span><span>(</span><span>self</span><span>):                    </span><span># print / str() 时调用</span></div></div><div><div><div>7</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"《</span><span>{</span><span>self</span><span>.title</span><span>}</span><span>》¥</span><span>{</span><span>self</span><span>.price</span><span>}</span><span>"</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>def</span><span> </span><span>__repr__</span><span>(</span><span>self</span><span>):                   </span><span># 调试/容器内显示时调用</span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"Book(</span><span>{</span><span>self</span><span>.title</span><span>!r</span><span>}</span><span>, </span><span>{</span><span>self</span><span>.price</span><span>}</span><span>)"</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>def</span><span> </span><span>__eq__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>other</span></span><span>):              </span><span># == 比较</span></div></div><div><div><div>13</div></div><div><span>        </span><span>return</span><span> </span><span>isinstance</span><span>(other, Book) </span><span>and</span><span> </span><span>self</span><span><span>.title </span><span>==</span><span> other.title</span></span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>    </span><span>def</span><span> </span><span>__lt__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>other</span></span><span>):              </span><span># &lt; 比较（配合 sort）</span></div></div><div><div><div>16</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span><span>.price </span><span>&lt;</span><span> other.price</span></span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>def</span><span> </span><span>__len__</span><span>(</span><span>self</span><span>):                    </span><span># len() 行为</span></div></div><div><div><div>19</div></div><div><span>        </span><span>return</span><span> </span><span>len</span><span>(</span><span>self</span><span>.title)</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>def</span><span> </span><span>__add__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>other</span></span><span>):             </span><span># + 行为</span></div></div><div><div><div>22</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span><span>.price </span><span>+</span><span> other.price</span></span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span><span>b1 </span><span>=</span><span> </span><span>Book</span><span>(</span></span><span>"Python入门"</span><span>, </span><span>59</span><span>)</span></div></div><div><div><div>25</div></div><div><span><span>b2 </span><span>=</span><span> </span><span>Book</span><span>(</span></span><span>"Python入门"</span><span>, </span><span>79</span><span>)</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>print</span><span>(b1)                    </span><span># 《Python入门》¥59</span></div></div><div><div><div>28</div></div><div><span>print</span><span><span>(b1 </span><span>==</span><span> b2)              </span></span><span># True（同名即相等）</span></div></div><div><div><div>29</div></div><div><span><span>books </span><span>=</span><span> [</span><span>Book</span><span>(</span></span><span>"A书"</span><span>, </span><span>49</span><span><span>), </span><span>Book</span><span>(</span></span><span>"B书"</span><span>, </span><span>29</span><span>)]</span></div></div><div><div><div>30</div></div><div><span><span>books.</span><span>sort</span><span>()                 </span></span><span># 按 __lt__ 排序</span></div></div><div><div><div>31</div></div><div><span>print</span><span>(</span><span>len</span><span>(b1))               </span><span># 9（标题字符数）</span></div></div><div><div><div>32</div></div><div><span>print</span><span><span>(b1 </span><span>+</span><span> b2)               </span></span><span># 138（价格相加）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>常用魔法方法速查</strong>：</p>

<table><thead><tr><th>方法</th><th>触发时机</th></tr></thead><tbody><tr><td><code>__init__</code></td><td>创建实例</td></tr><tr><td><code>__str__</code> / <code>__repr__</code></td><td>print / 调试显示</td></tr><tr><td><code>__eq__</code> / <code>__lt__</code></td><td><code>==</code> / <code>&lt;</code>（排序）</td></tr><tr><td><code>__len__</code></td><td><code>len(obj)</code></td></tr><tr><td><code>__add__</code></td><td><code>obj + x</code></td></tr><tr><td><code>__iter__</code> / <code>__next__</code></td><td>for 遍历（第七篇）</td></tr><tr><td><code>__enter__</code> / <code>__exit__</code></td><td>with 语句</td></tr><tr><td><code>__getitem__</code></td><td><code>obj[key]</code></td></tr></tbody></table></section>
<section><h2>五、dataclass：数据类的省事写法（3.7+）<a href="#五dataclass数据类的省事写法37"><span>#</span></a></h2><p>纯存数据的类（学生、订单、配置）可用 <code>@dataclass</code> 自动生成 <code>__init__</code>、<code>__repr__</code>、<code>__eq__</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> dataclasses </span><span>import</span><span> dataclass, field</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>@dataclass</span></div></div><div><div><div>4</div></div><div><span>class</span><span><span> </span><span>Student</span></span><span>:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>name: </span><span>str</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>age: </span><span>int</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>scores: </span><span>list</span><span><span> </span><span>=</span><span> </span><span>field</span><span>(</span></span><span>default_factory</span><span>=</span><span>list</span><span>)   </span><span># 可变默认值的安全写法</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>def</span><span> </span><span>average</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span><span> </span><span>sum</span><span>(</span><span>self</span><span><span>.scores) </span><span>/</span><span> </span></span><span>len</span><span>(</span><span>self</span><span>.scores) </span><span>if</span><span> </span><span>self</span><span>.scores </span><span>else</span><span> </span><span>0</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>s </span><span>=</span><span> </span><span>Student</span><span>(</span></span><span>"小明"</span><span>, </span><span>18</span><span>, [</span><span>90</span><span>, </span><span>85</span><span>])</span></div></div><div><div><div>13</div></div><div><span>print</span><span>(s)                 </span><span># Student(name='小明', age=18, scores=[90, 85])</span></div></div><div><div><div>14</div></div><div><span>print</span><span><span>(s.</span><span>average</span><span>())       </span></span><span># 87.5</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>相比手写，省掉 80% 样板代码，现代 Python 写数据类的首选。</p></section>
<section><h2>六、综合实战：图书馆管理系统<a href="#六综合实战图书馆管理系统"><span>#</span></a></h2><p>把本篇全部知识串起来：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> dataclasses </span><span>import</span><span> dataclass, field</span></div></div><div><div><div>2</div></div><div><span>from</span><span> datetime </span><span>import</span><span> date, timedelta</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>class</span><span><span> </span><span>LibraryError</span><span>(</span></span><span>Exception</span><span>)</span><span>:</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"""图书馆业务异常"""</span></div></div><div><div><div>6</div></div><div><span>    </span><span>pass</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>@dataclass</span></div></div><div><div><div>9</div></div><div><span>class</span><span><span> </span><span>Book</span></span><span>:</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>isbn: </span><span>str</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>title: </span><span>str</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>copies: </span><span>int</span><span><span> </span><span>=</span><span> </span></span><span>1</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>borrowers: </span><span>list</span><span><span> </span><span>=</span><span> </span><span>field</span><span>(</span></span><span>default_factory</span><span>=</span><span>list</span><span>)</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>@</span><span>property</span></div></div><div><div><div>16</div></div><div><span>    </span><span>def</span><span> </span><span>available</span><span>(</span><span>self</span><span>) -&gt; </span><span>int</span><span>:</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span> </span><span>self</span><span><span>.copies </span><span>-</span><span> </span></span><span>len</span><span>(</span><span>self</span><span>.borrowers)</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>class</span><span><span> </span><span>Member</span></span><span>:</span></div></div><div><div><div>20</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>mid</span></span><span>:</span><span> </span><span>int</span><span>,</span><span><span> </span><span>name</span></span><span>:</span><span> </span><span>str</span><span>):</span></div></div><div><div><div>21</div></div><div><span>        </span><span>self</span><span><span>.mid </span><span>=</span><span> mid</span></span></div></div><div><div><div>22</div></div><div><span>        </span><span>self</span><span><span>.name </span><span>=</span><span> name</span></span></div></div><div><div><div>23</div></div><div><span>        </span><span>self</span><span>.borrowed: dict[</span><span>str</span><span><span>, date] </span><span>=</span><span> {}     </span></span><span># isbn -&gt; 应还日期</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>    </span><span>def</span><span> </span><span>__str__</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>26</div></div><div><span>        </span><span>return</span><span> </span><span>f</span><span>"会员</span><span>{</span><span>self</span><span>.mid</span><span>}</span><span>-</span><span>{</span><span>self</span><span>.name</span><span>}</span><span>（在借</span><span>{</span><span>len</span><span>(</span><span>self</span><span>.borrowed)</span><span>}</span><span>本）"</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>class</span><span><span> </span><span>Library</span></span><span>:</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>LOAN_DAYS</span><span> </span><span>=</span><span> </span><span>30</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>MAX_BOOKS</span><span> </span><span>=</span><span> </span><span>3</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>33</div></div><div><span>        </span><span>self</span><span>._books: dict[</span><span>str</span><span><span>, Book] </span><span>=</span><span> {}</span></span></div></div><div><div><div>34</div></div><div><span>        </span><span>self</span><span>._members: dict[</span><span>int</span><span><span>, Member] </span><span>=</span><span> {}</span></span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>    </span><span>def</span><span> </span><span>add_book</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>isbn</span></span><span>,</span><span><span> </span><span>title</span></span><span>,</span><span><span> </span><span>copies</span></span><span>=</span><span>1</span><span>):</span></div></div><div><div><div>37</div></div><div><span>        </span><span>if</span><span> isbn </span><span>in</span><span> </span><span>self</span><span>._books:</span></div></div><div><div><div>38</div></div><div><span>            </span><span>self</span><span><span>._books[isbn].copies </span><span>+=</span><span> copies</span></span></div></div><div><div><div>39</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>40</div></div><div><span>            </span><span>self</span><span><span>._books[isbn] </span><span>=</span><span> </span><span>Book</span><span>(isbn, title, copies)</span></span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>    </span><span>def</span><span> </span><span>register</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>name</span></span><span>) -&gt; Member:</span></div></div><div><div><div>43</div></div><div><span><span>        </span></span><span>mid </span><span>=</span><span> </span><span>max</span><span>(</span><span>self</span><span>._members, </span><span>default</span><span>=</span><span>0</span><span><span>) </span><span>+</span><span> </span></span><span>1</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>m </span><span>=</span><span> </span><span>Member</span><span>(mid, name)</span></div></div><div><div><div>45</div></div><div><span>        </span><span>self</span><span><span>._members[mid] </span><span>=</span><span> m</span></span></div></div><div><div><div>46</div></div><div><span>        </span><span>return</span><span> m</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>    </span><span>def</span><span> </span><span>borrow</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>member</span></span><span>:</span><span> Member</span><span>,</span><span><span> </span><span>isbn</span></span><span>:</span><span> </span><span>str</span><span>):</span></div></div><div><div><div>49</div></div><div><span>        </span><span>"""借书：封装所有业务规则校验"""</span></div></div><div><div><div>50</div></div><div><span><span>        </span></span><span>book </span><span>=</span><span> </span><span>self</span><span><span>._books.</span><span>get</span><span>(isbn)</span></span></div></div><div><div><div>51</div></div><div><span>        </span><span>if</span><span> book </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>52</div></div><div><span>            </span><span>raise</span><span><span> </span><span>LibraryError</span><span>(</span></span><span>f</span><span>"无此书: </span><span>{</span><span>isbn</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>53</div></div><div><span>        </span><span>if</span><span><span> book.available </span><span>&lt;=</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>54</div></div><div><span>            </span><span>raise</span><span><span> </span><span>LibraryError</span><span>(</span></span><span>f</span><span>"《</span><span>{</span><span>book.title</span><span>}</span><span>》已全部借出"</span><span>)</span></div></div><div><div><div>55</div></div><div><span>        </span><span>if</span><span> </span><span>len</span><span><span>(member.borrowed) </span><span>&gt;=</span><span> </span></span><span>self</span><span><span>.</span><span>MAX_BOOKS</span><span>:</span></span></div></div><div><div><div>56</div></div><div><span>            </span><span>raise</span><span><span> </span><span>LibraryError</span><span>(</span></span><span>f</span><span>"</span><span>{</span><span>member.name</span><span>}</span><span> 已达借阅上限</span><span>{</span><span>self</span><span><span>.</span><span>MAX_BOOKS</span></span><span>}</span><span>本"</span><span>)</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span><span>        </span></span><span>book.borrowers.</span><span>append</span><span>(member.name)</span></div></div><div><div><div>59</div></div><div><span><span>        </span></span><span>member.borrowed[isbn] </span><span>=</span><span> date.</span><span>today</span><span>() </span><span>+</span><span> </span><span>timedelta</span><span>(</span><span>days</span><span>=</span><span>self</span><span><span>.</span><span>LOAN_DAYS</span><span>)</span></span></div></div><div><div><div>60</div></div><div>
</div></div><div><div><div>61</div></div><div><span>    </span><span>def</span><span> </span><span>return_book</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>member</span></span><span>:</span><span> Member</span><span>,</span><span><span> </span><span>isbn</span></span><span>:</span><span> </span><span>str</span><span>):</span></div></div><div><div><div>62</div></div><div><span>        </span><span>if</span><span> isbn </span><span>not</span><span> </span><span>in</span><span> member.borrowed:</span></div></div><div><div><div>63</div></div><div><span>            </span><span>raise</span><span><span> </span><span>LibraryError</span><span>(</span></span><span>f</span><span>"</span><span>{</span><span>member.name</span><span>}</span><span> 没借这本书"</span><span>)</span></div></div><div><div><div>64</div></div><div><span>        </span><span>self</span><span><span>._books[isbn].borrowers.</span><span>remove</span><span>(member.name)</span></span></div></div><div><div><div>65</div></div><div><span>        </span><span>del</span><span> member.borrowed[isbn]</span></div></div><div><div><div>66</div></div><div>
</div></div><div><div><div>67</div></div><div><span>    </span><span>def</span><span> </span><span>__len__</span><span>(</span><span>self</span><span>):                          </span><span># len(图书馆) = 藏书种数</span></div></div><div><div><div>68</div></div><div><span>        </span><span>return</span><span> </span><span>len</span><span>(</span><span>self</span><span>._books)</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span>    </span><span>def</span><span> </span><span>__contains__</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>isbn</span></span><span>):               </span><span># isbn in 图书馆</span></div></div><div><div><div>71</div></div><div><span>        </span><span>return</span><span> isbn </span><span>in</span><span> </span><span>self</span><span>._books</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span># —— 使用 ——</span></div></div><div><div><div>74</div></div><div><span><span>lib </span><span>=</span><span> </span><span>Library</span><span>()</span></span></div></div><div><div><div>75</div></div><div><span><span>lib.</span><span>add_book</span><span>(</span></span><span>"978-7-111-40701-0"</span><span>, </span><span>"Python编程：从入门到实践"</span><span>, </span><span>copies</span><span>=</span><span>2</span><span>)</span></div></div><div><div><div>76</div></div><div><span><span>lib.</span><span>add_book</span><span>(</span></span><span>"978-7-115-53608-2"</span><span>, </span><span>"算法（第4版）"</span><span>)</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span><span>ming </span><span>=</span><span> lib.</span><span>register</span><span>(</span></span><span>"小明"</span><span>)</span></div></div><div><div><div>79</div></div><div><span><span>lib.</span><span>borrow</span><span>(ming, </span></span><span>"978-7-111-40701-0"</span><span>)</span></div></div><div><div><div>80</div></div><div><span>print</span><span>(ming)                                   </span><span># 会员1-小明（在借1本）</span></div></div><div><div><div>81</div></div><div><span>print</span><span>(</span><span>f</span><span>"馆藏 </span><span>{</span><span>len</span><span>(lib)</span><span>}</span><span> 种；'978-7-115-53608-2' 在馆: </span><span>{</span><span>'978-7-115-53608-2'</span><span> </span><span>in</span><span> lib</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>82</div></div><div>
</div></div><div><div><div>83</div></div><div><span><span>lib.</span><span>return_book</span><span>(ming, </span></span><span>"978-7-111-40701-0"</span><span>)</span></div></div><div><div><div>84</div></div><div><span>print</span><span>(ming)                                   </span><span># 会员1-小明（在借0本）</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>这个案例用到的知识点</strong>：dataclass、property、封装（<code>_books</code> 内部字典）、自定义异常、魔法方法 <code>__len__</code>/<code>__contains__</code>、类型注解。建议自己敲一遍再扩展（比如加逾期罚款计算）。</p></section>
<section><h2>七、什么时候用 OOP<a href="#七什么时候用-oop"><span>#</span></a></h2>

<table><thead><tr><th>场景</th><th>建议</th></tr></thead><tbody><tr><td>一次脚本、简单流程</td><td>函数式足够，别硬上类</td></tr><tr><td>多个实体有各自状态（游戏角色、订单）</td><td>类</td></tr><tr><td>框架开发 / 库开发</td><td>类（用户需要可组合的抽象）</td></tr><tr><td>数据 + 行为强绑定</td><td>类</td></tr><tr><td>纯数据传递</td><td>dataclass</td></tr></tbody></table><p>Python 支持多范式：<strong>工具函数直接写函数，业务实体才建类</strong>，不要为了 OOP 而 OOP。</p></section>
<section><h2>小练习<a href="#小练习"><span>#</span></a></h2><ol>
<li>定义 <code>Rectangle</code> 类：宽高属性、<code>area</code>/<code>perimeter</code> 方法、<code>__eq__</code>（面积相等即相等）</li>
<li>写 <code>BankAccount</code>：<code>__init__(owner, balance)</code>、<code>deposit</code>、<code>withdraw</code>（余额不足抛自定义 <code>InsufficientFundsError</code>）、<code>__str__</code></li>
<li>定义 <code>Shape</code> 基类 + <code>Circle</code>/<code>Square</code> 子类，各实现 <code>area()</code>，写函数打印一组图形的面积与总和（多态）</li>
<li>给 <code>Book</code> 加 <code>__iter__</code>，使其能 <code>for chapter in book</code> 遍历章节名列表</li>
<li>（综合）扩展图书馆：会员分级（学生可借 3 本 30 天 / 教师可借 10 本 60 天），用继承实现</li>
</ol></section>
<section><h2>本篇小结<a href="#本篇小结"><span>#</span></a></h2><ul>
<li>类是图纸、实例是产品；<code>__init__</code> 构造、<code>self</code> 是实例自己</li>
<li>类属性共享、实例属性独立；查找顺序实例 → 类 → 父类</li>
<li>封装靠 <code>_</code> 约定；property 让方法像属性（可校验可只读）</li>
<li>继承复用、<code>super().__init__</code> 先父后子；重写实现多态；鸭子类型只看方法不看血统</li>
<li>魔法方法接入 Python 语法（print/==/len/+）；数据类用 <code>@dataclass</code></li>
<li>OOP 时机：多实体 + 各自状态；脚本工具用函数就好</li>
</ul><p><strong>下一篇</strong>：综合项目实战——从需求到成品的完整开发流程。</p><hr /><p><em>本系列为 Cyber先锋社原创教程。图书馆案例值得反复把玩——把它扩展成你的期末作品也毫不逊色。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/python-tutorial-11/</id>
      <title type="text">Python 入门教程（十一）：综合实战——命令行待办事项管理器</title>
      <published>2026-10-29T00:00:00.000Z</published>
      <updated>2026-10-29T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/python-tutorial-11/"/>
      <summary type="text">系列收官之作：从需求分析到架构设计，综合运用函数、字典、JSON 持久化、异常处理、模块拆分，完整开发一个可增删改查、筛选统计、命令行交互的待办事项管理器，含完整源码。</summary>
      <content type="html"><![CDATA[<section><h2>本篇目标<a href="#本篇目标"><span>#</span></a></h2><p>十篇知识点集于一身：<strong>做一个完整可用的命令行待办事项管理器（Todo CLI）</strong>。你会经历真实项目的全流程——需求分析 → 架构设计 → 分模块实现 → 测试 → 打磨。做完这个项目，你就不是”学过 Python”，而是”用 Python 做过东西”。</p></section>
<section><h2>一、需求分析<a href="#一需求分析"><span>#</span></a></h2><p>先明确产品要做什么（真实项目第一步）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>功能需求：</span></div></div><div><div><div>2</div></div><div><span>1. 添加任务：标题 + 可选优先级（高/中/低）+ 可选截止日期</span></div></div><div><div><div>3</div></div><div><span>2. 查看任务：全部 / 未完成 / 已完成 / 按优先级筛选</span></div></div><div><div><div>4</div></div><div><span>3. 完成任务：按编号标记完成</span></div></div><div><div><div>5</div></div><div><span>4. 删除任务</span></div></div><div><div><div>6</div></div><div><span>5. 数据持久化：退出后数据还在（JSON 文件）</span></div></div><div><div><div>7</div></div><div><span>6. 统计：总数、完成率、逾期数</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>非功能需求：</span></div></div><div><div><div>10</div></div><div><span>- 输入容错：非法输入不崩溃，给出友好提示</span></div></div><div><div><div>11</div></div><div><span>- 单文件可运行，也方便扩展成多模块</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>二、架构设计<a href="#二架构设计"><span>#</span></a></h2><p>数据结构先行——一个任务长什么样：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"id"</span><span>: </span><span>1</span><span>,                       </span><span># 自增编号</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"title"</span><span>: </span><span>"写Python作业"</span><span>,        </span><span># 标题</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"priority"</span><span>: </span><span>"high"</span><span>,            </span><span># high / mid / low</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"due"</span><span>: </span><span>"2026-11-05"</span><span>,           </span><span># 截止日期（可空）</span></div></div><div><div><div>6</div></div><div><span>    </span><span>"done"</span><span>: </span><span>False</span><span>,                 </span><span># 是否完成</span></div></div><div><div><div>7</div></div><div><span>    </span><span>"created"</span><span>: </span><span>"2026-10-29 12:00"</span><span>  </span><span># 创建时间</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>模块划分</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>todo.py</span></div></div><div><div><div>2</div></div><div><span>├── 数据层：load / save（JSON 读写，第九篇）</span></div></div><div><div><div>3</div></div><div><span>├── 业务层：add / done / delete / list / stats（函数，第六篇）</span></div></div><div><div><div>4</div></div><div><span>├── 展示层：渲染表格、彩色输出</span></div></div><div><div><div>5</div></div><div><span>└── 交互层：main 循环解析命令（第八篇 sys.argv 思想 → 交互式菜单）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>分层原则：<strong>业务函数不 print 结果而是返回数据，展示层负责打印</strong>——这样以后加 Web 界面能直接复用业务层。</p></section>
<section><h2>三、完整实现<a href="#三完整实现"><span>#</span></a></h2><p>逐段实现（可直接拼成完整文件）：</p><section><h3>1. 数据层<a href="#1-数据层"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> json</span></div></div><div><div><div>2</div></div><div><span>import</span><span> os</span></div></div><div><div><div>3</div></div><div><span>from</span><span> datetime </span><span>import</span><span> datetime</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>DATA_FILE</span><span> </span><span>=</span><span> </span></span><span>"todos.json"</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>load_todos</span><span>():</span></div></div><div><div><div>8</div></div><div><span>    </span><span>"""读取数据文件；不存在或损坏时返回空列表（健壮性）"""</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span><span> os.path.</span><span>exists</span><span>(</span><span>DATA_FILE</span><span>):</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>return</span><span> []</span></div></div><div><div><div>11</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>12</div></div><div><span>        </span><span>with</span><span> </span><span>open</span><span><span>(</span><span>DATA_FILE</span><span>, </span></span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>13</div></div><div><span>            </span><span>return</span><span><span> json.</span><span>load</span><span>(f)</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>except</span><span> (json.JSONDecodeError, </span><span>OSError</span><span>):</span></div></div><div><div><div>15</div></div><div><span>        </span><span>print</span><span>(</span><span>"⚠ 数据文件损坏，已重置"</span><span>)</span></div></div><div><div><div>16</div></div><div><span>        </span><span>return</span><span> []</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>def</span><span> </span><span>save_todos</span><span>(</span><span>todos</span><span>):</span></div></div><div><div><div>19</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span><span>(</span><span>DATA_FILE</span><span>, </span></span><span>"w"</span><span>, </span><span>encoding</span><span>=</span><span>"utf-8"</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>json.</span><span>dump</span><span>(todos, f, </span><span>ensure_ascii</span><span>=</span><span>False</span><span>, </span><span>indent</span><span>=</span><span>2</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>2. 业务层<a href="#2-业务层"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>VALID_PRIORITIES</span><span> </span><span>=</span><span> {</span></span><span>"high"</span><span>: </span><span>"🔴高"</span><span>, </span><span>"mid"</span><span>: </span><span>"🟡中"</span><span>, </span><span>"low"</span><span>: </span><span>"🟢低"</span><span>}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>def</span><span> </span><span>next_id</span><span>(</span><span>todos</span><span>):</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>max</span><span>((t[</span><span>"id"</span><span>] </span><span>for</span><span> t </span><span>in</span><span> todos), </span><span>default</span><span>=</span><span>0</span><span><span>) </span><span>+</span><span> </span></span><span>1</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>def</span><span> </span><span>add_todo</span><span>(</span><span>todos</span><span>,</span><span><span> </span><span>title</span></span><span>,</span><span><span> </span><span>priority</span></span><span>=</span><span>"mid"</span><span>,</span><span><span> </span><span>due</span></span><span>=</span><span>None</span><span>):</span></div></div><div><div><div>7</div></div><div><span>    </span><span>"""新增任务，返回新任务"""</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> priority </span><span>not</span><span> </span><span>in</span><span><span> </span><span>VALID_PRIORITIES</span><span>:</span></span></div></div><div><div><div>9</div></div><div><span>        </span><span>raise</span><span> </span><span>ValueError</span><span>(</span><span>f</span><span>"优先级必须是 </span><span>{</span><span>list</span><span><span>(</span><span>VALID_PRIORITIES</span><span>)</span></span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>10</div></div><div><span>    </span><span>if</span><span> due:</span></div></div><div><div><div>11</div></div><div><span>        </span><span>try</span><span>:</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>datetime.</span><span>strptime</span><span>(due, </span><span>"%Y-%m-</span><span>%d</span><span>"</span><span>)    </span><span># 校验日期格式</span></div></div><div><div><div>13</div></div><div><span>        </span><span>except</span><span> </span><span>ValueError</span><span>:</span></div></div><div><div><div>14</div></div><div><span>            </span><span>raise</span><span> </span><span>ValueError</span><span>(</span><span>"日期格式应为 YYYY-MM-DD"</span><span>)</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>todo </span><span>=</span><span> {</span></div></div><div><div><div>16</div></div><div><span>        </span><span>"id"</span><span><span>: </span><span>next_id</span><span>(todos),</span></span></div></div><div><div><div>17</div></div><div><span>        </span><span>"title"</span><span><span>: title.</span><span>strip</span><span>(),</span></span></div></div><div><div><div>18</div></div><div><span>        </span><span>"priority"</span><span>: priority,</span></div></div><div><div><div>19</div></div><div><span>        </span><span>"due"</span><span>: due,</span></div></div><div><div><div>20</div></div><div><span>        </span><span>"done"</span><span>: </span><span>False</span><span>,</span></div></div><div><div><div>21</div></div><div><span>        </span><span>"created"</span><span><span>: datetime.</span><span>now</span><span>().</span><span>strftime</span><span>(</span></span><span>"%Y-%m-</span><span>%d</span><span> %H:%M"</span><span>),</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>todos.</span><span>append</span><span>(todo)</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>save_todos</span><span>(todos)</span></div></div><div><div><div>25</div></div><div><span>    </span><span>return</span><span> todo</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>def</span><span> </span><span>finish_todo</span><span>(</span><span>todos</span><span>,</span><span><span> </span><span>todo_id</span></span><span>):</span></div></div><div><div><div>28</div></div><div><span>    </span><span>"""标记完成，返回该任务；不存在抛 KeyError"""</span></div></div><div><div><div>29</div></div><div><span>    </span><span>for</span><span> t </span><span>in</span><span> todos:</span></div></div><div><div><div>30</div></div><div><span>        </span><span>if</span><span> t[</span><span>"id"</span><span><span>] </span><span>==</span><span> todo_id:</span></span></div></div><div><div><div>31</div></div><div><span><span>            </span></span><span>t[</span><span>"done"</span><span><span>] </span><span>=</span><span> </span></span><span>True</span></div></div><div><div><div>32</div></div><div><span><span>            </span></span><span>save_todos</span><span>(todos)</span></div></div><div><div><div>33</div></div><div><span>            </span><span>return</span><span> t</span></div></div><div><div><div>34</div></div><div><span>    </span><span>raise</span><span> </span><span>KeyError</span><span>(</span><span>f</span><span>"找不到编号 </span><span>{</span><span>todo_id</span><span>}</span><span> 的任务"</span><span>)</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>def</span><span> </span><span>delete_todo</span><span>(</span><span>todos</span><span>,</span><span><span> </span><span>todo_id</span></span><span>):</span></div></div><div><div><div>37</div></div><div><span>    </span><span>for</span><span> i, t </span><span>in</span><span> </span><span>enumerate</span><span>(todos):</span></div></div><div><div><div>38</div></div><div><span>        </span><span>if</span><span> t[</span><span>"id"</span><span><span>] </span><span>==</span><span> todo_id:</span></span></div></div><div><div><div>39</div></div><div><span><span>            </span></span><span>removed </span><span>=</span><span> todos.</span><span>pop</span><span>(i)</span></div></div><div><div><div>40</div></div><div><span><span>            </span></span><span>save_todos</span><span>(todos)</span></div></div><div><div><div>41</div></div><div><span>            </span><span>return</span><span> removed</span></div></div><div><div><div>42</div></div><div><span>    </span><span>raise</span><span> </span><span>KeyError</span><span>(</span><span>f</span><span>"找不到编号 </span><span>{</span><span>todo_id</span><span>}</span><span> 的任务"</span><span>)</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>def</span><span> </span><span>query</span><span>(</span><span>todos</span><span>,</span><span><span> </span><span>status</span></span><span>=</span><span>"all"</span><span>,</span><span><span> </span><span>priority</span></span><span>=</span><span>None</span><span>):</span></div></div><div><div><div>45</div></div><div><span>    </span><span>"""筛选：status = all/todo/done；priority = high/mid/low"""</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>result </span><span>=</span><span> todos</span></div></div><div><div><div>47</div></div><div><span>    </span><span>if</span><span><span> status </span><span>==</span><span> </span></span><span>"todo"</span><span>:</span></div></div><div><div><div>48</div></div><div><span><span>        </span></span><span>result </span><span>=</span><span> [t </span><span>for</span><span> t </span><span>in</span><span> result </span><span>if</span><span> </span><span>not</span><span> t[</span><span>"done"</span><span>]]</span></div></div><div><div><div>49</div></div><div><span>    </span><span>elif</span><span><span> status </span><span>==</span><span> </span></span><span>"done"</span><span>:</span></div></div><div><div><div>50</div></div><div><span><span>        </span></span><span>result </span><span>=</span><span> [t </span><span>for</span><span> t </span><span>in</span><span> result </span><span>if</span><span> t[</span><span>"done"</span><span>]]</span></div></div><div><div><div>51</div></div><div><span>    </span><span>if</span><span> priority:</span></div></div><div><div><div>52</div></div><div><span><span>        </span></span><span>result </span><span>=</span><span> [t </span><span>for</span><span> t </span><span>in</span><span> result </span><span>if</span><span> t[</span><span>"priority"</span><span><span>] </span><span>==</span><span> priority]</span></span></div></div><div><div><div>53</div></div><div><span>    </span><span>return</span><span> result</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>def</span><span> </span><span>is_overdue</span><span>(</span><span>todo</span><span>):</span></div></div><div><div><div>56</div></div><div><span>    </span><span>"""已过期：未完成且截止日早于今天"""</span></div></div><div><div><div>57</div></div><div><span>    </span><span>if</span><span> todo[</span><span>"done"</span><span>] </span><span>or</span><span> </span><span>not</span><span> todo[</span><span>"due"</span><span>]:</span></div></div><div><div><div>58</div></div><div><span>        </span><span>return</span><span> </span><span>False</span></div></div><div><div><div>59</div></div><div><span>    </span><span>return</span><span> todo[</span><span>"due"</span><span><span>] </span><span>&lt;</span><span> datetime.</span><span>now</span><span>().</span><span>strftime</span><span>(</span></span><span>"%Y-%m-</span><span>%d</span><span>"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>3. 展示层<a href="#3-展示层"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>print_todos</span><span>(</span><span>todos</span><span>,</span><span><span> </span><span>title</span></span><span>=</span><span>"任务列表"</span><span>):</span></div></div><div><div><div>2</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span> todos:</span></div></div><div><div><div>3</div></div><div><span>        </span><span>print</span><span>(</span><span>"（空空如也）"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>        </span><span>return</span></div></div><div><div><div>5</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>\n</span><span>== </span><span>{</span><span>title</span><span>}</span><span> =="</span><span>)</span></div></div><div><div><div>6</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>'ID'</span><span>:&lt;5</span><span>}{</span><span>'状态'</span><span>:&lt;6</span><span>}{</span><span>'优先级'</span><span>:&lt;8</span><span>}{</span><span>'截止'</span><span>:&lt;12</span><span>}</span><span>标题"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>    </span><span>print</span><span>(</span><span>"-"</span><span><span> </span><span>*</span><span> </span></span><span>50</span><span>)</span></div></div><div><div><div>8</div></div><div><span>    </span><span>for</span><span> t </span><span>in</span><span> todos:</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>status </span><span>=</span><span> </span><span>"✅"</span><span> </span><span>if</span><span> t[</span><span>"done"</span><span>] </span><span>else</span><span> (</span><span>"⏳"</span><span> </span><span>if</span><span> </span><span>not</span><span><span> </span><span>is_overdue</span><span>(t) </span></span><span>else</span><span> </span><span>"❗逾期"</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>due </span><span>=</span><span> t[</span><span>"due"</span><span>] </span><span>or</span><span> </span><span>"-"</span></div></div><div><div><div>11</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"</span><span>{</span><span>t[</span><span>'id'</span><span>]</span><span>:&lt;5</span><span>}{</span><span>status</span><span>:&lt;6</span><span>}{</span><span><span>VALID_PRIORITIES</span><span>[t[</span></span><span>'priority'</span><span>]]</span><span>:&lt;6</span><span>}</span><span>"</span></div></div><div><div><div>12</div></div><div><span>              </span><span>f</span><span>"</span><span>{</span><span>due</span><span>:&lt;12</span><span>}{</span><span>t[</span><span>'title'</span><span>]</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>def</span><span> </span><span>print_stats</span><span>(</span><span>todos</span><span>):</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>total </span><span>=</span><span> </span><span>len</span><span>(todos)</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>done </span><span>=</span><span> </span><span>sum</span><span>(</span><span>1</span><span> </span><span>for</span><span> t </span><span>in</span><span> todos </span><span>if</span><span> t[</span><span>"done"</span><span>])</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>overdue </span><span>=</span><span> </span><span>sum</span><span>(</span><span>1</span><span> </span><span>for</span><span> t </span><span>in</span><span> todos </span><span>if</span><span><span> </span><span>is_overdue</span><span>(t))</span></span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>rate </span><span>=</span><span> done </span><span>/</span><span> total </span><span>*</span><span> </span><span>100</span><span> </span><span>if</span><span> total </span><span>else</span><span> </span><span>0</span></div></div><div><div><div>19</div></div><div><span>    </span><span>print</span><span>(</span><span>f</span><span>"</span><span>\n</span><span>📊 统计：共 </span><span>{</span><span>total</span><span>}</span><span> 项｜完成 </span><span>{</span><span>done</span><span>}</span><span> 项"</span></div></div><div><div><div>20</div></div><div><span>          </span><span>f</span><span>"（</span><span>{</span><span>rate</span><span>:.0f</span><span>}</span><span>%）｜逾期 </span><span>{</span><span>overdue</span><span>}</span><span> 项"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>4. 交互层<a href="#4-交互层"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>def</span><span> </span><span>main</span><span>():</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>todos </span><span>=</span><span> </span><span>load_todos</span><span>()</span></div></div><div><div><div>3</div></div><div><span>    </span><span>print</span><span>(</span><span>"=== 待办事项管理器 ==="</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>print</span><span>(</span><span>"命令：add 标题 [优先级] [日期] / list [all|todo|done] / "</span></div></div><div><div><div>5</div></div><div><span>          </span><span>"done 编号 / del 编号 / stats / quit"</span><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>8</div></div><div><span>        </span><span>try</span><span>:</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>raw </span><span>=</span><span> </span><span>input</span><span>(</span><span>"</span><span>\n</span><span>&gt; "</span><span><span>).</span><span>strip</span><span>()</span></span></div></div><div><div><div>10</div></div><div><span>            </span><span>if</span><span> </span><span>not</span><span> raw:</span></div></div><div><div><div>11</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>parts </span><span>=</span><span> raw.</span><span>split</span><span>(</span><span>maxsplit</span><span>=</span><span>3</span><span>)      </span><span># 最多拆 4 段，标题保留空格</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>cmd, args </span><span>=</span><span> parts[</span><span>0</span><span><span>].</span><span>lower</span><span>(), parts[</span></span><span>1</span><span>:]</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>            </span><span>if</span><span><span> cmd </span><span>==</span><span> </span></span><span>"quit"</span><span>:</span></div></div><div><div><div>16</div></div><div><span>                </span><span>print</span><span>(</span><span>"再见！"</span><span>)</span></div></div><div><div><div>17</div></div><div><span>                </span><span>break</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>            </span><span>elif</span><span><span> cmd </span><span>==</span><span> </span></span><span>"add"</span><span>:</span></div></div><div><div><div>20</div></div><div><span><span>                </span></span><span>title </span><span>=</span><span> args[</span><span>0</span><span>] </span><span>if</span><span> args </span><span>else</span><span> </span><span>""</span></div></div><div><div><div>21</div></div><div><span>                </span><span>if</span><span> </span><span>not</span><span> title:</span></div></div><div><div><div>22</div></div><div><span>                    </span><span>print</span><span>(</span><span>"用法：add 标题 [high|mid|low] [YYYY-MM-DD]"</span><span>)</span></div></div><div><div><div>23</div></div><div><span>                    </span><span>continue</span></div></div><div><div><div>24</div></div><div><span><span>                </span></span><span>priority </span><span>=</span><span> args[</span><span>1</span><span>] </span><span>if</span><span> </span><span>len</span><span><span>(args) </span><span>&gt;</span><span> </span></span><span>1</span><span> </span><span>and</span><span> args[</span><span>1</span><span>] </span><span>in</span><span><span> </span><span>VALID_PRIORITIES</span><span> </span></span><span>else</span><span> </span><span>"mid"</span></div></div><div><div><div>25</div></div><div><span><span>                </span></span><span>due </span><span>=</span><span> args[</span><span>2</span><span>] </span><span>if</span><span> </span><span>len</span><span><span>(args) </span><span>&gt;</span><span> </span></span><span>2</span><span> </span><span>else</span><span> </span><span>None</span></div></div><div><div><div>26</div></div><div><span><span>                </span></span><span>t </span><span>=</span><span> </span><span>add_todo</span><span>(todos, title, priority, due)</span></div></div><div><div><div>27</div></div><div><span>                </span><span>print</span><span>(</span><span>f</span><span>"✅ 已添加 #</span><span>{</span><span>t[</span><span>'id'</span><span>]</span><span>}</span><span> </span><span>{</span><span>t[</span><span>'title'</span><span>]</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>            </span><span>elif</span><span><span> cmd </span><span>==</span><span> </span></span><span>"list"</span><span>:</span></div></div><div><div><div>30</div></div><div><span><span>                </span></span><span>status </span><span>=</span><span> args[</span><span>0</span><span>] </span><span>if</span><span> args </span><span>and</span><span> args[</span><span>0</span><span>] </span><span>in</span><span> (</span><span>"all"</span><span>, </span><span>"todo"</span><span>, </span><span>"done"</span><span>) </span><span>else</span><span> </span><span>"todo"</span></div></div><div><div><div>31</div></div><div><span><span>                </span></span><span>print_todos</span><span>(</span><span>query</span><span>(todos, </span><span>status</span><span><span>=</span><span>status), </span></span><span>f</span><span>"筛选:</span><span>{</span><span>status</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>            </span><span>elif</span><span><span> cmd </span><span>==</span><span> </span></span><span>"done"</span><span>:</span></div></div><div><div><div>34</div></div><div><span><span>                </span></span><span>finish_todo</span><span>(todos, </span><span>int</span><span>(args[</span><span>0</span><span>]))</span></div></div><div><div><div>35</div></div><div><span>                </span><span>print</span><span>(</span><span>"🎉 已完成！"</span><span>)</span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>            </span><span>elif</span><span><span> cmd </span><span>==</span><span> </span></span><span>"del"</span><span>:</span></div></div><div><div><div>38</div></div><div><span><span>                </span></span><span>delete_todo</span><span>(todos, </span><span>int</span><span>(args[</span><span>0</span><span>]))</span></div></div><div><div><div>39</div></div><div><span>                </span><span>print</span><span>(</span><span>"🗑 已删除"</span><span>)</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>            </span><span>elif</span><span><span> cmd </span><span>==</span><span> </span></span><span>"stats"</span><span>:</span></div></div><div><div><div>42</div></div><div><span><span>                </span></span><span>print_stats</span><span>(todos)</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>45</div></div><div><span>                </span><span>print</span><span>(</span><span>"未知命令，输入 quit 退出"</span><span>)</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>        </span><span>except</span><span> </span><span>KeyError</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>48</div></div><div><span>            </span><span>print</span><span>(</span><span>f</span><span>"操作失败：</span><span>{</span><span>e</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>49</div></div><div><span>        </span><span>except</span><span> </span><span>ValueError</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>50</div></div><div><span>            </span><span>print</span><span>(</span><span>f</span><span>"参数错误：</span><span>{</span><span>e</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>51</div></div><div><span>        </span><span>except</span><span> </span><span>IndexError</span><span>:</span></div></div><div><div><div>52</div></div><div><span>            </span><span>print</span><span>(</span><span>"缺少参数，请检查命令格式"</span><span>)</span></div></div><div><div><div>53</div></div><div><span>        </span><span>except</span><span> </span><span>KeyboardInterrupt</span><span>:</span></div></div><div><div><div>54</div></div><div><span>            </span><span>print</span><span>(</span><span>"</span><span>\n</span><span>再见！"</span><span>)</span></div></div><div><div><div>55</div></div><div><span>            </span><span>break</span></div></div><div><div><div>56</div></div><div>
</div></div><div><div><div>57</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>"__main__"</span><span>:      </span><span># 第八篇：可直接运行，也可被导入复用</span></div></div><div><div><div>58</div></div><div><span><span>    </span></span><span>main</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h2>四、运行演示<a href="#四运行演示"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>=== 待办事项管理器 ===</span></div></div><div><div><div>2</div></div><div><span>&gt; add 复习Python教程 high 2026-10-30</span></div></div><div><div><div>3</div></div><div><span>✅ 已添加 #1 复习Python教程</span></div></div><div><div><div>4</div></div><div><span>&gt; add 给社团投稿</span></div></div><div><div><div>5</div></div><div><span>✅ 已添加 #2 给社团投稿</span></div></div><div><div><div>6</div></div><div><span>&gt; add 买咖啡 low</span></div></div><div><div><div>7</div></div><div><span>✅ 已添加 #3 买咖啡</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>&gt; list all</span></div></div><div><div><div>10</div></div><div><span>== 筛选:all ==</span></div></div><div><div><div>11</div></div><div><span>ID   状态    优先级  截止        标题</span></div></div><div><div><div>12</div></div><div><span>--------------------------------------------------</span></div></div><div><div><div>13</div></div><div><span>1    ⏳    🔴高   2026-10-30 复习Python教程</span></div></div><div><div><div>14</div></div><div><span>2    ⏳    🟡中   -          给社团投稿</span></div></div><div><div><div>15</div></div><div><span>3    ⏳    🟢低   -          买咖啡</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>&gt; done 3</span></div></div><div><div><div>18</div></div><div><span>🎉 已完成！</span></div></div><div><div><div>19</div></div><div><span>&gt; stats</span></div></div><div><div><div>20</div></div><div><span>📊 统计：共 3 项｜完成 1 项（33%）｜逾期 0 项</span></div></div><div><div><div>21</div></div><div><span>&gt; quit</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>重启程序，数据完好——<code>todos.json</code> 在工作目录里。</p></section>
<section><h2>五、自测清单（交付前必做）<a href="#五自测清单交付前必做"><span>#</span></a></h2><p>真实项目的验收环节，逐项跑一遍：</p><ul>
<li> <code>add</code> 不带任何参数 → 提示用法，不崩溃</li>
<li> <code>add 测试 xyz</code>（非法优先级）→ 自动降级为 mid，不崩溃</li>
<li> <code>add 测试 mid 2026-13-99</code> → 提示日期格式错误</li>
<li> <code>done 999</code> → 提示找不到，不崩溃</li>
<li> 数据文件手动改成乱码 → 启动提示损坏并重置</li>
<li> 完成/删除后重启 → 状态保持</li>
<li> 造一条昨天截止的任务 → list 显示”❗逾期”</li>
</ul><p>全部通过，才算”完成”。<strong>这就是教程规则里”代码必须可运行”的含义</strong>。</p></section>
<section><h2>六、进阶改造方向<a href="#六进阶改造方向"><span>#</span></a></h2><p>这个骨架能长成什么：</p><ol>
<li><strong>多模块拆分</strong>：按架构图拆成 <code>storage.py / core.py / ui.py</code>（第八篇的包结构）</li>
<li><strong>命令行参数版</strong>：用标准库 <code>argparse</code> 改造为 <code>python todo.py add "标题" -p high</code></li>
<li><strong>Web 化</strong>：加 Flask/FastAPI 路由包装业务层——因为业务与展示分离，几乎不用改核心</li>
<li><strong>数据升级</strong>：JSON → SQLite（标准库 sqlite3），支持按标题搜索</li>
<li><strong>定时提醒</strong>：结合 <code>datetime</code> 循环检测逾期任务并弹通知</li>
</ol></section>
<section><h2>七、系列总结<a href="#七系列总结"><span>#</span></a></h2><p>11 篇走过的路：</p>

<table><thead><tr><th>篇</th><th>主题</th><th>核心收获</th></tr></thead><tbody><tr><td>1</td><td>环境与变量</td><td>安装、交互环境、四大类型</td></tr><tr><td>2</td><td>运算符与字符串</td><td>七类运算、切片、f-string</td></tr><tr><td>3</td><td>条件与循环</td><td>if/while/for、break/continue、推导式</td></tr><tr><td>4</td><td>列表与元组</td><td>增删改查、排序、深浅拷贝</td></tr><tr><td>5</td><td>字典与集合</td><td>键值映射、去重、集合运算</td></tr><tr><td>6</td><td>函数</td><td>参数全家族、作用域、lambda、闭包</td></tr><tr><td>7</td><td>迭代器与生成器</td><td>迭代协议、yield、省内存</td></tr><tr><td>8</td><td>模块与标准库</td><td>导入、虚拟环境、六大库</td></tr><tr><td>9</td><td>文件与异常</td><td>with、精确捕获、自定义异常</td></tr><tr><td>10</td><td>面向对象</td><td>类、封装、继承多态、魔法方法</td></tr><tr><td>11</td><td>综合实战（本篇）</td><td>分层架构、完整项目流程</td></tr></tbody></table><p><strong>下一步建议</strong>：C++ / Java 系列横向对照着学一遍（体会静态类型与编译）；或者直接挑一个小工具（自己用的）从零做出来——<strong>做东西是唯一的学习闭环</strong>。做出作品欢迎投稿到本站，或到留言板晒成果。</p></section>
<section><h2>小练习（毕业设计，三选一）<a href="#小练习毕业设计三选一"><span>#</span></a></h2><ol>
<li>给 Todo 加”标签”功能：<code>add 标题 #标签</code>，<code>list #作业</code> 按标签筛</li>
<li>做”单词打卡器”：每日录入生词与释义，随机抽测，答对率统计（random + json + datetime）</li>
<li>把 Todo 拆成三模块的包并加 <code>argparse</code> 命令行支持</li>
</ol><hr /><p><em>本系列为 Cyber先锋社原创教程，共 11 篇。完成毕业设计的同学，欢迎在留言板认领晒图名额！</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/ctf-beginners-guide/</id>
      <title type="text">CTF 入门指南：什么是 CTF，如何开始你的第一道题？</title>
      <published>2026-10-28T00:00:00.000Z</published>
      <updated>2026-10-28T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/ctf-beginners-guide/"/>
      <summary type="text">CTF（Capture The Flag）是网络安全领域最流行的竞赛形式。本文带你了解 CTF 的五大方向、常见题型与入门学习路径，帮你迈出网络安全竞赛的第一步。</summary>
      <content type="html"><![CDATA[<section><h2>什么是 CTF？<a href="#什么是-ctf"><span>#</span></a></h2><p><strong>CTF（Capture The Flag，夺旗赛）</strong> 是网络安全领域最流行的技术竞赛形式。参赛选手需要通过分析题目环境，找到隐藏在其中的特定格式的字符串（即 “Flag”），例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>flag{w3lc0me_t0_cyber_p10neer}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>CTF 不仅是一场比赛，更是检验和提升安全技能的最佳实践场。社团后续的训练营也将围绕 CTF 展开。</p></section>
<section><h2>五大主流方向<a href="#五大主流方向"><span>#</span></a></h2>

<table><thead><tr><th>方向</th><th>主要内容</th><th>需要的基础</th></tr></thead><tbody><tr><td><strong>Web</strong></td><td>SQL 注入、XSS、SSRF、文件上传漏洞等</td><td>HTTP 协议、Python、前后端基础</td></tr><tr><td><strong>Pwn</strong></td><td>栈溢出、堆漏洞、格式化字符串等二进制利用</td><td>C 语言、汇编、Linux 系统</td></tr><tr><td><strong>Reverse</strong></td><td>逆向分析程序逻辑、破解算法</td><td>C/C++、汇编、耐心</td></tr><tr><td><strong>Crypto</strong></td><td>古典密码、RSA、AES 等密码学攻击</td><td>数论、Python</td></tr><tr><td><strong>Misc</strong></td><td>流量分析、隐写、取证等杂项</td><td>广泛的知识面</td></tr></tbody></table><div><div><div></div><div>Tip</div></div><div><p>新手建议从 <strong>Web</strong> 或 <strong>Misc</strong> 入手，门槛相对友好；有 C 语言基础的同学可以直接挑战 <strong>Pwn</strong> 和 <strong>Reverse</strong>。</p></div></div></section>
<section><h2>入门学习路径<a href="#入门学习路径"><span>#</span></a></h2><section><h3>第一步：搭建环境<a href="#第一步搭建环境"><span>#</span></a></h3><p>一台 Linux 虚拟机（推荐 Ubuntu 或 Kali）几乎是标配：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># Ubuntu 下安装常用工具</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>python3</span><span> </span><span>python3-pip</span><span> </span><span>git</span><span> </span><span>curl</span><span> </span><span>burpsuite</span><span> </span><span>wireshark</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>第二步：刷题入门<a href="#第二步刷题入门"><span>#</span></a></h3><p>推荐从国内的新手友好平台开始：</p><ul>
<li><strong>BUUCTF</strong>（buuoj.cn）：题目收录全面，writeup 丰富</li>
<li><strong>攻防世界</strong>（adworld.xctf.org.cn）：分类清晰，适合按方向刷题</li>
<li><strong>PicoCTF</strong>：纯英文，但题目设计非常适合零基础</li>
</ul></section><section><h3>第三步：学会复盘<a href="#第三步学会复盘"><span>#</span></a></h3><p>每做完一道题，建议写一篇简短的 writeup，记录：</p><ol>
<li>题目考察的知识点</li>
<li>自己卡壳的地方</li>
<li>别人的更优解法</li>
</ol><p>坚持复盘是快速成长的关键，优秀的 writeup 也可以投稿到本站，与大家分享。</p></section></section>
<section><h2>社团训练计划<a href="#社团训练计划"><span>#</span></a></h2><p>社团 CTF 训练营每两周一次线下活动，形式包括：</p><ul>
<li><strong>入门专题讲座</strong>：由高年级社员或校外讲师主讲</li>
<li><strong>组队模拟赛</strong>：还原真实比赛节奏，赛后集体复盘</li>
<li><strong>年度重点赛事</strong>：组队参加 XCTF、强网杯、网鼎杯等赛事</li>
</ul><p>具体时间安排请关注站内公告与社团群通知。</p><hr /><p><em>有问题随时在社团群里提问，期待在赛场上看到你的身影！</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/how-this-blog-was-built/</id>
      <title type="text">本博客的诞生记录：Astro + Firefly 建站全流程</title>
      <published>2026-10-28T00:00:00.000Z</published>
      <updated>2026-10-28T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/how-this-blog-was-built/"/>
      <summary type="text">记录 Cyber先锋社官方博客从框架选型到上线的完整过程：为什么选择 Astro + Firefly？静态博客如何部署？本文也是一份可复用的建站思路参考。</summary>
      <content type="html"><![CDATA[<section><h2>为什么选择静态博客<a href="#为什么选择静态博客"><span>#</span></a></h2><p>社团官网的核心需求很简单：<strong>展示文章、稳定、省资源、好维护</strong>。对比了几个方案：</p>

<table><thead><tr><th>方案</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>WordPress</td><td>生态大、后台完善</td><td>PHP + MySQL，资源占用高，需要持续打补丁</td></tr><tr><td>Halo</td><td>国产、界面现代</td><td>需要 Java 运行时，内存占用高</td></tr><tr><td><strong>Astro 静态站</strong></td><td>零数据库、纯静态文件、速度快</td><td>更新内容需要重新构建</td></tr></tbody></table><p>我们的服务器配置不高，静态方案几乎不占运行时资源，nginx 托管静态文件的内存开销可以忽略，安全性也远好于动态 CMS——最终选择 <strong>Astro + Firefly 主题</strong>。</p></section>
<section><h2>技术栈一览<a href="#技术栈一览"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>博客框架     Astro v7（静态站点生成）</span></div></div><div><div><div>2</div></div><div><span>主题         Firefly（基于 Fuwari 二次开发）</span></div></div><div><div><div>3</div></div><div><span>包管理器     pnpm</span></div></div><div><div><div>4</div></div><div><span>源码托管     GitHub - 1376524890/cyberpioneer_blog</span></div></div><div><div><div>5</div></div><div><span>Web 服务     nginx（托管静态文件）</span></div></div><div><div><div>6</div></div><div><span>部署方式     源码推 GitHub → 服务器拉取构建 → 同步上线</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>本地开发流程<a href="#本地开发流程"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 安装依赖（需要 Node.js &gt;= 22.23）</span></div></div><div><div><div>2</div></div><div><span>corepack</span><span> </span><span>enable</span></div></div><div><div><div>3</div></div><div><span>pnpm</span><span> </span><span>install</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 本地预览 http://localhost:4321</span></div></div><div><div><div>6</div></div><div><span>pnpm</span><span> </span><span>dev</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 构建静态站点到 dist/</span></div></div><div><div><div>9</div></div><div><span>pnpm</span><span> </span><span>build</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h3>写一篇新文章<a href="#写一篇新文章"><span>#</span></a></h3><p>文章以 Markdown 格式存放在 <code>src/content/posts/</code> 目录，只需复制一份模板修改 frontmatter：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>---</span></div></div><div><div><div>2</div></div><div><span>title</span><span>: </span><span>文章标题</span></div></div><div><div><div>3</div></div><div><span>published</span><span>: </span><span>2026-10-28</span></div></div><div><div><div>4</div></div><div><span>description</span><span>: </span><span>一句话摘要，会显示在列表页</span></div></div><div><div><div>5</div></div><div><span>tags</span><span>: [</span><span>标签1</span><span>, </span><span>标签2</span><span>]</span></div></div><div><div><div>6</div></div><div><span>category</span><span>: </span><span>分类名</span></div></div><div><div><div>7</div></div><div><span>slug</span><span>: </span><span>url-friendly-slug</span></div></div><div><div><div>8</div></div><div><span>---</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>正文支持 Markdown……</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>保存后推送到 GitHub，服务器端拉取重新构建即可上线。</p></section></section>
<section><h2>部署要点<a href="#部署要点"><span>#</span></a></h2><p>静态博客的部署非常简单：任意一台 Linux 服务器 + nginx 托管 <code>dist/</code> 目录即可。下面是一份通用的 nginx 站点配置示例（端口与路径按自己环境调整）：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>server</span><span> {</span></div></div><div><div><div>2</div></div><div><span>   <span> </span></span><span>listen </span><span>80</span><span> </span><span>default_server</span><span>;</span></div></div><div><div><div>3</div></div><div><span>   <span> </span></span><span>listen </span><span>[::]:80 </span><span>default_server</span><span>;</span></div></div><div><div><div>4</div></div><div><span>   <span> </span></span><span>server_name </span><span>_;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>   <span> </span></span><span>root </span><span>/var/www/blog;   </span><span># 指向构建产物目录</span></div></div><div><div><div>7</div></div><div><span>   <span> </span></span><span>index </span><span>index.html;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span># Astro 默认带尾斜杠</span></div></div><div><div><div>10</div></div><div><span>    </span><span>location</span><span> / {</span></div></div><div><div><div>11</div></div><div><span>       <span> </span></span><span>try_files </span><span>$</span><span>uri</span><span> $</span><span>uri</span><span>/ $</span><span>uri</span><span>/index.html </span><span>=404</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span># 静态资源长缓存</span></div></div><div><div><div>15</div></div><div><span>    </span><span>location</span><span> /_astro/ {</span></div></div><div><div><div>16</div></div><div><span>       <span> </span></span><span>expires </span><span>30d</span><span>;</span></div></div><div><div><div>17</div></div><div><span>       <span> </span></span><span>add_header </span><span>Cache-Control </span><span>"public, immutable"</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>   <span> </span></span><span>gzip </span><span>on</span><span>;</span></div></div><div><div><div>21</div></div><div><span>   <span> </span></span><span>gzip_types </span><span>text/css application/javascript image/svg+xml application/json;</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>我们的更新流程：源码推送到 GitHub 后，在服务器上拉取、构建，再把 <code>dist/</code> 同步到站点目录，一条脚本搞定。出于安全考虑，服务器的具体信息不在此公开。</p></section>
<section><h2>一点心得<a href="#一点心得"><span>#</span></a></h2><ul>
<li>静态博客把安全面缩到最小：没有数据库、没有后台登录、没有插件供应链</li>
<li>GitHub 管源码，服务器只管渲染结果，职责清晰</li>
<li>小内存机器跑 nginx + 静态文件毫无压力，轻松扛住校园级流量</li>
</ul><hr /><p><em>如果你也想给社团或自己搭一个博客，欢迎在群里交流，我们可以出一份保姆级教程。</em></p></section>]]></content>
    </entry>
    <entry>
      <id>https://www.cyberpioneer.club/posts/web-security-sql-injection-basics/</id>
      <title type="text">Web 安全入门：从一个 SQL 注入的诞生说起</title>
      <published>2026-10-28T00:00:00.000Z</published>
      <updated>2026-10-28T00:00:00.000Z</updated>
      <author><name>Cyber先锋社</name></author>
      <link rel="alternate" href="https://www.cyberpioneer.club/posts/web-security-sql-injection-basics/"/>
      <summary type="text">SQL 注入是 Web 安全中最经典、影响面最广的漏洞之一。本文以一个极简的登录接口为例，带你直观理解 SQL 注入的成因、利用方式与正确防御手段，适合刚接触 Web 安全的同学阅读。</summary>
      <content type="html"><![CDATA[<section><h2>从一段有问题的代码说起<a href="#从一段有问题的代码说起"><span>#</span></a></h2><p>假设一个校园活动报名系统，用下面这段 PHP 代码验证用户登录：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>&lt;</span><span>?</span></span><span>php</span></div></div><div><div><div>2</div></div><div><span>// ⚠️ 危险代码，仅作教学演示</span></div></div><div><div><div>3</div></div><div><span>$username</span><span><span> </span><span>=</span><span> </span></span><span>$_POST</span><span>[</span><span>'username'</span><span>];</span></div></div><div><div><div>4</div></div><div><span>$password</span><span><span> </span><span>=</span><span> </span></span><span>$_POST</span><span>[</span><span>'password'</span><span>];</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>$sql</span><span><span> </span><span>=</span><span> </span></span><span>"</span><span>SELECT</span><span><span> </span><span>*</span><span> </span></span><span>FROM</span><span> users</span></div></div><div><div><div>7</div></div><div><span>        </span><span>WHERE</span><span><span> username</span><span>=</span></span><span>'</span><span>$username</span><span>'</span></div></div><div><div><div>8</div></div><div><span>        </span><span>AND</span><span> </span><span>password</span><span>=</span><span>'</span><span>$password</span><span>'"</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>$result</span><span><span> </span><span>=</span><span> </span></span><span>$db</span><span>-&gt;</span><span>query</span><span>(</span><span>$sql</span><span>);</span></div></div><div><div><div>11</div></div><div><span>if</span><span> (</span><span>$result</span><span>-&gt;</span><span>num_rows</span><span><span> </span><span>&gt;</span><span> </span></span><span>0</span><span>) {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>echo</span><span> </span><span>"登录成功"</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这段代码在功能上完全正常——正常用户输入正确的账号密码，就能登录成功。</p><p>但问题出在：<strong>用户输入被直接拼接进了 SQL 语句</strong>。</p></section>
<section><h2>注入是如何发生的<a href="#注入是如何发生的"><span>#</span></a></h2><p>如果攻击者在密码框输入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>' OR '</span><span>1</span><span>'='</span><span>1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么最终执行的 SQL 变成了：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>SELECT</span><span> * </span><span>FROM</span><span> users</span></div></div><div><div><div>2</div></div><div><span>WHERE</span><span><span> username</span><span>=</span></span><span>'admin'</span></div></div><div><div><div>3</div></div><div><span>AND</span><span> </span><span>password</span><span>=</span><span>''</span><span> </span><span>OR</span><span> </span><span>'1'</span><span>=</span><span>'1'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>由于 <code>'1'='1'</code> 恒为真，这个查询条件永远成立，攻击者在<strong>不知道密码的情况下以 admin 身份登录</strong>——这就是一次最经典的 SQL 注入攻击。</p><div><div><div></div><div>Warning</div></div><div><p>本文所有内容仅用于教学演示。对未授权系统进行测试是违法行为，请在合法靶场环境中练习。</p></div></div></section>
<section><h2>更进一步：万能密码与信息刺探<a href="#更进一步万能密码与信息刺探"><span>#</span></a></h2><section><h3>探测列数<a href="#探测列数"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>admin</span><span>' ORDER BY 3-- -</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>逐步增大数字，根据页面报错判断查询结果的列数。</p></section><section><h3>联合查询读取数据<a href="#联合查询读取数据"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>' UNION SELECT username, password FROM users-- -</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>通过 <code>UNION</code> 把数据库中的敏感数据直接拼进页面返回。</p></section><section><h3>数据库指纹<a href="#数据库指纹"><span>#</span></a></h3><p>不同数据库的函数和报错信息各有特征：</p>

<table><thead><tr><th>数据库</th><th>探测语句</th></tr></thead><tbody><tr><td>MySQL</td><td><code>SELECT version()</code></td></tr><tr><td>PostgreSQL</td><td><code>SELECT version()</code></td></tr><tr><td>SQLite</td><td><code>SELECT sqlite_version()</code></td></tr></tbody></table></section></section>
<section><h2>正确的防御姿势<a href="#正确的防御姿势"><span>#</span></a></h2><section><h3>1. 参数化查询（最有效）<a href="#1-参数化查询最有效"><span>#</span></a></h3><p>预编译让用户输入永远只作为”数据”而不是”代码”被处理：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>&lt;</span><span>?</span></span><span>php</span></div></div><div><div><div>2</div></div><div><span>// ✅ 正确做法：参数化查询</span></div></div><div><div><div>3</div></div><div><span>$stmt</span><span><span> </span><span>=</span><span> </span></span><span>$db</span><span>-&gt;</span><span>prepare</span><span>(</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"</span><span>SELECT</span><span><span> </span><span>*</span><span> </span></span><span>FROM</span><span> users </span><span>WHERE</span><span><span> username</span><span>=</span><span>? </span></span><span>AND</span><span> </span><span>password</span><span><span>=</span><span>?</span></span><span>"</span></div></div><div><div><div>5</div></div><div><span>);</span></div></div><div><div><div>6</div></div><div><span>$stmt</span><span>-&gt;</span><span>bind_param</span><span>(</span><span>"ss"</span><span>, </span><span>$username</span><span>, </span><span>$password</span><span>);</span></div></div><div><div><div>7</div></div><div><span>$stmt</span><span>-&gt;</span><span>execute</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Python (SQLAlchemy) 示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span> sqlalchemy </span><span>import</span><span> text</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># ✅ 绑定参数，输入不会被当作 SQL 执行</span></div></div><div><div><div>4</div></div><div><span><span>db.</span><span>execute</span><span>(</span></span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>text</span><span>(</span><span>"SELECT * FROM users WHERE username=:u AND password=:p"</span><span>),</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>{</span><span>"u"</span><span>: username, </span><span>"p"</span><span>: password},</span></div></div><div><div><div>7</div></div><div><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 最小权限原则<a href="#2-最小权限原则"><span>#</span></a></h3><p>应用连接数据库的账号只授予必要权限，即使被注入也难以 <code>DROP TABLE</code>。</p></section><section><h3>3. 输入校验与 WAF<a href="#3-输入校验与-waf"><span>#</span></a></h3><p>对输入做白名单校验、部署 WAF 可以增加攻击难度，但<strong>都不能替代参数化查询</strong>。</p></section></section>
<section><h2>动手练习<a href="#动手练习"><span>#</span></a></h2><p>想亲手试试？推荐这些合法靶场：</p><ul>
<li><strong>sqli-labs</strong>：经典的 SQL 注入练习靶场</li>
<li><strong>DVWA</strong>：综合型 Web 漏洞演练平台</li>
<li><strong>Pikachu</strong>：中文界面的入门友好靶场</li>
</ul><p>社团活动室常年开放靶机环境，具体开放时间见群公告。</p><hr /><p><em>下一篇文章我们聊聊 XSS：当攻击者的脚本在你的浏览器里运行时会发生什么。</em></p></section>]]></content>
    </entry>
</feed>
