[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-javazifuchuansanjianketexingchangjingyubikengzhinan":3},{"id":4,"title":5,"slug":6,"summary":7,"content":8,"contentHtml":9,"wordCount":10,"readingTime":11,"categoryId":12,"tags":13,"coverImage":13,"thumbnail":13,"status":14,"isTop":15,"isRecommended":15,"allowComments":15,"password":13,"viewCount":16,"likeCount":15,"commentCount":15,"seoTitle":5,"seoKeywords":17,"seoDescription":18,"source":13,"sourceUrl":13,"publishTime":19},"2003005387844939778","Java字符串三剑客：特性、场景与避坑指南","javazifuchuansanjianketexingchangjingyubikengzhinan","> 在Java开发中，String、StringBuffer和StringBuilder是处理文本的核心类。选择不当会引发性能问题和线程安全隐患。下面通过对比介绍和代码示例，帮助你精准选用。 ## 1 核心特性对比 下面的表格直观对比了这三个类的核心差异，方便您快速把握重点。 | 特性 | String | StringBuilder | StringBuffer | | :--- | :--- | :--- | :--- | | **可变性** | ❌ 不可变 | ✅ 可变 | ✅ 可变 | | **线程安全** | ✅ 安全（因不可变） | ❌ 不安全 | ✅ 安全（synchronized实现） | | **性能** | 低（频繁修改时） | 高（单线程最佳） | 中（有同步开销） | | **适用场景** | 常量、少量操作 | 单线程下大量修改 | 多线程下大量修改 | **简单...","> 在Java开发中，String、StringBuffer和StringBuilder是处理文本的核心类。选择不当会引发性能问题和线程安全隐患。下面通过对比介绍和代码示例，帮助你精准选用。\n## 1 核心特性对比\n\n下面的表格直观对比了这三个类的核心差异，方便您快速把握重点。\n\n| 特性 | String | StringBuilder | StringBuffer |\n| :--- | :--- | :--- | :--- |\n| **可变性** | ❌ 不可变 | ✅ 可变 | ✅ 可变 |\n| **线程安全** | ✅ 安全（因不可变） | ❌ 不安全 | ✅ 安全（synchronized实现） |\n| **性能** | 低（频繁修改时） | 高（单线程最佳） | 中（有同步开销） |\n| **适用场景** | 常量、少量操作 | 单线程下大量修改 | 多线程下大量修改 |\n\n**简单来说**：\n- **String** 是字符串**常量**，适用于表示那些一旦创建就不再改变的值。\n- **StringBuilder** 和 **StringBuffer** 是字符串**变量**，适用于需要频繁修改字符串内容的场景。两者的核心区别在于**线程安全**。\n\n## 2 各对象详解与使用场景\n\n### 2.1 String：不可变的常量\n\n- **本质特性**：`String` 对象一旦创建，其内容就无法更改。任何看似修改的操作（如拼接、替换）都会**创建一个新的String对象**，原有的对象不会改变。\n- **线程安全**：由于其不可变性，`String` 对象是天然线程安全的，可以在多线程间安全共享。\n- **性能影响**：正因为每次修改都会产生新对象，在频繁进行字符串操作的场景下（尤其是在循环中），会产生大量临时对象，增加垃圾回收（GC）的压力，导致性能低下。\n\n#### ✅ 适用场景\n- 字符串内容不经常变化，例如常量的声明、配置项。\n- 作为 `HashMap` 等集合的键（因其不可变性保证了哈希值的稳定）。\n- 简单的、少量的字符串拼接。\n\n### 2.2 StringBuilder：单线程下的性能王者\n\n- **本质特性**：`StringBuilder` 是可变的字符序列。它可以在原对象上进行修改，而不会创建新的对象。\n- **线程安全**：**非线程安全**。它的方法没有使用 `synchronized` 关键字修饰，因此在多线程环境下使用可能导致数据不一致。\n- **性能**：由于没有同步开销，在单线程环境下，其性能是三者中最高的。\n\n#### ✅ 适用场景\n- **单线程环境**下需要**频繁**进行字符串拼接、插入、删除等操作。\n- 动态构建SQL语句、JSON字符串、XML数据等。\n- 日志信息的组装。\n\n### 2.3 StringBuffer：多线程环境的安全卫士\n\n- **本质特性**：`StringBuffer` 也是可变的字符序列，基本功能与 `StringBuilder` 相同。\n- **线程安全**：**线程安全**。其公开方法大多使用了 `synchronized` 关键字进行同步，从而保证在多线程环境下的操作是安全的。\n- **性能**：由于同步锁带来的开销，其性能通常低于 `StringBuilder`。\n\n#### ✅ 适用场景\n- **多线程环境**下需要频繁修改字符串。\n- 作为多个线程共享的字符串缓冲区，例如全局的日志收集器。\n\n## 3 常见错误示例与正确写法\n\n### 3.1 错误1：在循环中使用 String 拼接\n\n这是最常见且对性能影响最大的错误之一。\n\n#### ❌ 错误代码\n```java\nString result = \"\";\nfor (int i = 0; i \u003C 10000; i++) {\n    result += i; \u002F\u002F 每次循环都会创建新的String对象！\n}\n```\n**问题**：在循环体内，每次 `+=` 操作都会创建一个新的 `String` 对象（包含之前的全部内容和新增内容）。循环1万次将产生1万个临时对象，极度浪费内存和CPU。\n\n#### ✅ 正确代码\n使用 `StringBuilder` 来替代。\n```java\nStringBuilder sb = new StringBuilder(); \u002F\u002F 可预估最终长度时，建议指定初始容量，如new StringBuilder(20000)\nfor (int i = 0; i \u003C 10000; i++) {\n    sb.append(i);\n}\nString result = sb.toString();\n```\n**优势**：自始至终只操作一个 `StringBuilder` 对象，通过其内部的字符数组进行扩展，性能极高。\n\n### 3.2 错误2：无需线程安全时使用 StringBuffer\n\n#### ❌ 错误代码\n```java\n\u002F\u002F 在一个明确的单线程方法中\npublic String createGreeting(String name) {\n    StringBuffer sb = new StringBuffer(); \u002F\u002F 没有必要使用线程安全的StringBuffer\n    sb.append(\"Hello, \");\n    sb.append(name);\n    sb.append(\"!\");\n    return sb.toString();\n}\n```\n**问题**：在局部方法变量（不存在线程共享）中使用了 `StringBuffer`，其同步锁 `synchronized` 成为了不必要的性能开销。\n\n#### ✅ 正确代码\n改用更轻量的 `StringBuilder`。\n```java\npublic String createGreeting(String name) {\n    StringBuilder sb = new StringBuilder(); \u002F\u002F 单线程下性能更优\n    sb.append(\"Hello, \");\n    sb.append(name);\n    sb.append(\"!\");\n    return sb.toString();\n}\n```\n\n### 3.3 错误3：未正确初始化容量\n\n#### ❌ 错误代码\n```java\nStringBuilder sb = new StringBuilder(); \u002F\u002F 使用默认容量(16)\nfor (int i = 0; i \u003C 1000; i++) {\n    sb.append(\"a very long string...\"); \u002F\u002F 可能导致多次扩容\n}\n```\n**问题**：`StringBuilder` 和 `StringBuffer` 内部有容量概念。默认容量较小（如16字符），当追加的内容超过当前容量时，会触发扩容（创建新数组，复制旧数据）。频繁扩容影响性能。\n\n#### ✅ 正确代码\n如果能预估大致的最终大小，应在创建时指定初始容量。\n```java\n\u002F\u002F 预估最终字符串长度大约为 1000 * 20 = 20000 字符\nStringBuilder sb = new StringBuilder(20000);\nfor (int i = 0; i \u003C 1000; i++) {\n    sb.append(\"a very long string...\");\n}\n```\n\n### 3.4 错误4：多线程环境下错误共享 StringBuilder\n\n#### ❌ 错误代码\n```java\npublic class ThreadUnsafeExample {\n    private static StringBuilder sharedBuilder = new StringBuilder(); \u002F\u002F 非线程安全的对象被多个线程共享\n\n    public static void main(String[] args) throws InterruptedException {\n        Thread t1 = new Thread(() -> { sharedBuilder.append(\"Thread1 \"); });\n        Thread t2 = new Thread(() -> -> { sharedBuilder.append(\"Thread2 \"); });\n\n        t1.start();\n        t2.start();\n        t1.join();\n        t2.join();\n\n        System.out.println(sharedBuilder.toString()); \u002F\u002F 输出结果可能不一致或不完整\n    }\n}\n```\n**问题**：多个线程同时操作非线程安全的 `StringBuilder`，可能导致数据丢失、脏读或异常。\n\n#### ✅ 正确代码（视情况而定）\n1.  **使用 StringBuffer**（推荐）：\n    ```java\n    private static StringBuffer sharedBuffer = new StringBuffer(); \u002F\u002F 线程安全\n    ```\n2.  **使用线程隔离**（每个线程使用自己的 `StringBuilder`）：\n    ```java\n    private static final ThreadLocal\u003CStringBuilder> localBuilder = ThreadLocal.withInitial(StringBuilder::new);\n    \u002F\u002F 在每个线程内部调用 localBuilder.get().append(...)\n    ```\n\n## 4 实战技巧与最佳实践\n\n1.  **选型口诀**：\n    - **内容不变用 String**\n    - **单线程拼接用 StringBuilder**\n    - **多线程拼接用 StringBuffer**\n    - **循环拼接，绝不用 String！**\n\n2.  **简单拼接优化**：对于一次性拼接少量字符串（如 `\"Hello, \" + name`），现代Java编译器（JDK5+）会自动优化为 `StringBuilder` 操作，这种情况下直接使用 `+` 可读性更好，无需刻意创建 `StringBuilder`。\n\n3.  **API高效使用**：熟练使用 `append()`, `insert()`, `delete()`, `reverse()` 等方法，可以更灵活地操作字符串。\n\n## 总结\n\n理解 `String`、`StringBuilder` 和 `StringBuffer` 的本质区别是写出高效、健壮Java程序的关键。请记住这个核心原则：**根据字符串的“变化频率”和代码的“线程环境”来做出选择**。在大多数现代应用中，由于多数代码运行在单线程上下文（如Web请求的处理），`StringBuilder` 成为了最常用的选择。\n\n希望这份详细的指南能帮助你在实际开发中做出正确的选择。","\u003Cblockquote data-line=\"0\">\n\u003Cp data-line=\"0\">在Java开发中，String、StringBuffer和StringBuilder是处理文本的核心类。选择不当会引发性能问题和线程安全隐患。下面通过对比介绍和代码示例，帮助你精准选用。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch2 data-line=\"1\" id=\"1 核心特性对比\">1 核心特性对比\u003C\u002Fh2>\n\u003Cp data-line=\"3\">下面的表格直观对比了这三个类的核心差异，方便您快速把握重点。\u003C\u002Fp>\n\u003Ctable data-line=\"5\">\n\u003Cthead data-line=\"5\">\n\u003Ctr data-line=\"5\">\n\u003Cth style=\"text-align:left\">特性\u003C\u002Fth>\n\u003Cth style=\"text-align:left\">String\u003C\u002Fth>\n\u003Cth style=\"text-align:left\">StringBuilder\u003C\u002Fth>\n\u003Cth style=\"text-align:left\">StringBuffer\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody data-line=\"7\">\n\u003Ctr data-line=\"7\">\n\u003Ctd style=\"text-align:left\">\u003Cstrong>可变性\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">❌ 不可变\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">✅ 可变\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">✅ 可变\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"8\">\n\u003Ctd style=\"text-align:left\">\u003Cstrong>线程安全\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">✅ 安全（因不可变）\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">❌ 不安全\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">✅ 安全（synchronized实现）\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"9\">\n\u003Ctd style=\"text-align:left\">\u003Cstrong>性能\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">低（频繁修改时）\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">高（单线程最佳）\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">中（有同步开销）\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr data-line=\"10\">\n\u003Ctd style=\"text-align:left\">\u003Cstrong>适用场景\u003C\u002Fstrong>\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">常量、少量操作\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">单线程下大量修改\u003C\u002Ftd>\n\u003Ctd style=\"text-align:left\">多线程下大量修改\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Cp data-line=\"12\">\u003Cstrong>简单来说\u003C\u002Fstrong>：\u003C\u002Fp>\n\u003Cul data-line=\"13\">\n\u003Cli data-line=\"13\">\u003Cstrong>String\u003C\u002Fstrong> 是字符串\u003Cstrong>常量\u003C\u002Fstrong>，适用于表示那些一旦创建就不再改变的值。\u003C\u002Fli>\n\u003Cli data-line=\"14\">\u003Cstrong>StringBuilder\u003C\u002Fstrong> 和 \u003Cstrong>StringBuffer\u003C\u002Fstrong> 是字符串\u003Cstrong>变量\u003C\u002Fstrong>，适用于需要频繁修改字符串内容的场景。两者的核心区别在于\u003Cstrong>线程安全\u003C\u002Fstrong>。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 data-line=\"16\" id=\"2 各对象详解与使用场景\">2 各对象详解与使用场景\u003C\u002Fh2>\n\u003Ch3 data-line=\"18\" id=\"2.1 String：不可变的常量\">2.1 String：不可变的常量\u003C\u002Fh3>\n\u003Cul data-line=\"20\">\n\u003Cli data-line=\"20\">\u003Cstrong>本质特性\u003C\u002Fstrong>：\u003Ccode>String\u003C\u002Fcode> 对象一旦创建，其内容就无法更改。任何看似修改的操作（如拼接、替换）都会\u003Cstrong>创建一个新的String对象\u003C\u002Fstrong>，原有的对象不会改变。\u003C\u002Fli>\n\u003Cli data-line=\"21\">\u003Cstrong>线程安全\u003C\u002Fstrong>：由于其不可变性，\u003Ccode>String\u003C\u002Fcode> 对象是天然线程安全的，可以在多线程间安全共享。\u003C\u002Fli>\n\u003Cli data-line=\"22\">\u003Cstrong>性能影响\u003C\u002Fstrong>：正因为每次修改都会产生新对象，在频繁进行字符串操作的场景下（尤其是在循环中），会产生大量临时对象，增加垃圾回收（GC）的压力，导致性能低下。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch4 data-line=\"24\" id=\"✅ 适用场景\">✅ 适用场景\u003C\u002Fh4>\n\u003Cul data-line=\"25\">\n\u003Cli data-line=\"25\">字符串内容不经常变化，例如常量的声明、配置项。\u003C\u002Fli>\n\u003Cli data-line=\"26\">作为 \u003Ccode>HashMap\u003C\u002Fcode> 等集合的键（因其不可变性保证了哈希值的稳定）。\u003C\u002Fli>\n\u003Cli data-line=\"27\">简单的、少量的字符串拼接。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"29\" id=\"2.2 StringBuilder：单线程下的性能王者\">2.2 StringBuilder：单线程下的性能王者\u003C\u002Fh3>\n\u003Cul data-line=\"31\">\n\u003Cli data-line=\"31\">\u003Cstrong>本质特性\u003C\u002Fstrong>：\u003Ccode>StringBuilder\u003C\u002Fcode> 是可变的字符序列。它可以在原对象上进行修改，而不会创建新的对象。\u003C\u002Fli>\n\u003Cli data-line=\"32\">\u003Cstrong>线程安全\u003C\u002Fstrong>：\u003Cstrong>非线程安全\u003C\u002Fstrong>。它的方法没有使用 \u003Ccode>synchronized\u003C\u002Fcode> 关键字修饰，因此在多线程环境下使用可能导致数据不一致。\u003C\u002Fli>\n\u003Cli data-line=\"33\">\u003Cstrong>性能\u003C\u002Fstrong>：由于没有同步开销，在单线程环境下，其性能是三者中最高的。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch4 data-line=\"35\" id=\"✅ 适用场景\">✅ 适用场景\u003C\u002Fh4>\n\u003Cul data-line=\"36\">\n\u003Cli data-line=\"36\">\u003Cstrong>单线程环境\u003C\u002Fstrong>下需要\u003Cstrong>频繁\u003C\u002Fstrong>进行字符串拼接、插入、删除等操作。\u003C\u002Fli>\n\u003Cli data-line=\"37\">动态构建SQL语句、JSON字符串、XML数据等。\u003C\u002Fli>\n\u003Cli data-line=\"38\">日志信息的组装。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 data-line=\"40\" id=\"2.3 StringBuffer：多线程环境的安全卫士\">2.3 StringBuffer：多线程环境的安全卫士\u003C\u002Fh3>\n\u003Cul data-line=\"42\">\n\u003Cli data-line=\"42\">\u003Cstrong>本质特性\u003C\u002Fstrong>：\u003Ccode>StringBuffer\u003C\u002Fcode> 也是可变的字符序列，基本功能与 \u003Ccode>StringBuilder\u003C\u002Fcode> 相同。\u003C\u002Fli>\n\u003Cli data-line=\"43\">\u003Cstrong>线程安全\u003C\u002Fstrong>：\u003Cstrong>线程安全\u003C\u002Fstrong>。其公开方法大多使用了 \u003Ccode>synchronized\u003C\u002Fcode> 关键字进行同步，从而保证在多线程环境下的操作是安全的。\u003C\u002Fli>\n\u003Cli data-line=\"44\">\u003Cstrong>性能\u003C\u002Fstrong>：由于同步锁带来的开销，其性能通常低于 \u003Ccode>StringBuilder\u003C\u002Fcode>。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch4 data-line=\"46\" id=\"✅ 适用场景\">✅ 适用场景\u003C\u002Fh4>\n\u003Cul data-line=\"47\">\n\u003Cli data-line=\"47\">\u003Cstrong>多线程环境\u003C\u002Fstrong>下需要频繁修改字符串。\u003C\u002Fli>\n\u003Cli data-line=\"48\">作为多个线程共享的字符串缓冲区，例如全局的日志收集器。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 data-line=\"50\" id=\"3 常见错误示例与正确写法\">3 常见错误示例与正确写法\u003C\u002Fh2>\n\u003Ch3 data-line=\"52\" id=\"3.1 错误1：在循环中使用 String 拼接\">3.1 错误1：在循环中使用 String 拼接\u003C\u002Fh3>\n\u003Cp data-line=\"54\">这是最常见且对性能影响最大的错误之一。\u003C\u002Fp>\n\u003Ch4 data-line=\"56\" id=\"❌ 错误代码\">❌ 错误代码\u003C\u002Fh4>\n\n        \u003Cdetails  data-line=\"57\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">result\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C\u002Fspan>;\n\u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">i\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; i &lt; \u003Cspan class=\"hljs-number\">10000\u003C\u002Fspan>; i++) {\n    result += i; \u003Cspan class=\"hljs-comment\">\u002F\u002F 每次循环都会创建新的String对象！\u003C\u002Fspan>\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"63\">\u003Cstrong>问题\u003C\u002Fstrong>：在循环体内，每次 \u003Ccode>+=\u003C\u002Fcode> 操作都会创建一个新的 \u003Ccode>String\u003C\u002Fcode> 对象（包含之前的全部内容和新增内容）。循环1万次将产生1万个临时对象，极度浪费内存和CPU。\u003C\u002Fp>\n\u003Ch4 data-line=\"65\" id=\"✅ 正确代码\">✅ 正确代码\u003C\u002Fh4>\n\u003Cp data-line=\"66\">使用 \u003Ccode>StringBuilder\u003C\u002Fcode> 来替代。\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"67\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-type\">StringBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sb\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuilder\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 可预估最终长度时，建议指定初始容量，如new StringBuilder(20000)\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">i\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; i &lt; \u003Cspan class=\"hljs-number\">10000\u003C\u002Fspan>; i++) {\n    sb.append(i);\n}\n\u003Cspan class=\"hljs-type\">String\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">result\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> sb.toString();\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"74\">\u003Cstrong>优势\u003C\u002Fstrong>：自始至终只操作一个 \u003Ccode>StringBuilder\u003C\u002Fcode> 对象，通过其内部的字符数组进行扩展，性能极高。\u003C\u002Fp>\n\u003Ch3 data-line=\"76\" id=\"3.2 错误2：无需线程安全时使用 StringBuffer\">3.2 错误2：无需线程安全时使用 StringBuffer\u003C\u002Fh3>\n\u003Ch4 data-line=\"78\" id=\"❌ 错误代码\">❌ 错误代码\u003C\u002Fh4>\n\n        \u003Cdetails  data-line=\"79\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 在一个明确的单线程方法中\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> String \u003Cspan class=\"hljs-title function_\">createGreeting\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String name)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-type\">StringBuffer\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sb\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuffer\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 没有必要使用线程安全的StringBuffer\u003C\u002Fspan>\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;Hello, &quot;\u003C\u002Fspan>);\n    sb.append(name);\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;!&quot;\u003C\u002Fspan>);\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> sb.toString();\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"89\">\u003Cstrong>问题\u003C\u002Fstrong>：在局部方法变量（不存在线程共享）中使用了 \u003Ccode>StringBuffer\u003C\u002Fcode>，其同步锁 \u003Ccode>synchronized\u003C\u002Fcode> 成为了不必要的性能开销。\u003C\u002Fp>\n\u003Ch4 data-line=\"91\" id=\"✅ 正确代码\">✅ 正确代码\u003C\u002Fh4>\n\u003Cp data-line=\"92\">改用更轻量的 \u003Ccode>StringBuilder\u003C\u002Fcode>。\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"93\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> String \u003Cspan class=\"hljs-title function_\">createGreeting\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String name)\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-type\">StringBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sb\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuilder\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 单线程下性能更优\u003C\u002Fspan>\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;Hello, &quot;\u003C\u002Fspan>);\n    sb.append(name);\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;!&quot;\u003C\u002Fspan>);\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> sb.toString();\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch3 data-line=\"103\" id=\"3.3 错误3：未正确初始化容量\">3.3 错误3：未正确初始化容量\u003C\u002Fh3>\n\u003Ch4 data-line=\"105\" id=\"❌ 错误代码\">❌ 错误代码\u003C\u002Fh4>\n\n        \u003Cdetails  data-line=\"106\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-type\">StringBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sb\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuilder\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 使用默认容量(16)\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">i\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; i &lt; \u003Cspan class=\"hljs-number\">1000\u003C\u002Fspan>; i++) {\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;a very long string...&quot;\u003C\u002Fspan>); \u003Cspan class=\"hljs-comment\">\u002F\u002F 可能导致多次扩容\u003C\u002Fspan>\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"112\">\u003Cstrong>问题\u003C\u002Fstrong>：\u003Ccode>StringBuilder\u003C\u002Fcode> 和 \u003Ccode>StringBuffer\u003C\u002Fcode> 内部有容量概念。默认容量较小（如16字符），当追加的内容超过当前容量时，会触发扩容（创建新数组，复制旧数据）。频繁扩容影响性能。\u003C\u002Fp>\n\u003Ch4 data-line=\"114\" id=\"✅ 正确代码\">✅ 正确代码\u003C\u002Fh4>\n\u003Cp data-line=\"115\">如果能预估大致的最终大小，应在创建时指定初始容量。\u003C\u002Fp>\n\n        \u003Cdetails  data-line=\"116\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-comment\">\u002F\u002F 预估最终字符串长度大约为 1000 * 20 = 20000 字符\u003C\u002Fspan>\n\u003Cspan class=\"hljs-type\">StringBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sb\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuilder\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">20000\u003C\u002Fspan>);\n\u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-type\">int\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">i\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; i &lt; \u003Cspan class=\"hljs-number\">1000\u003C\u002Fspan>; i++) {\n    sb.append(\u003Cspan class=\"hljs-string\">&quot;a very long string...&quot;\u003C\u002Fspan>);\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Ch3 data-line=\"124\" id=\"3.4 错误4：多线程环境下错误共享 StringBuilder\">3.4 错误4：多线程环境下错误共享 StringBuilder\u003C\u002Fh3>\n\u003Ch4 data-line=\"126\" id=\"❌ 错误代码\">❌ 错误代码\u003C\u002Fh4>\n\n        \u003Cdetails  data-line=\"127\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ThreadUnsafeExample\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">StringBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sharedBuilder\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuilder\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 非线程安全的对象被多个线程共享\u003C\u002Fspan>\n\n    \u003Cspan class=\"hljs-keyword\">public\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">main\u003C\u002Fspan>\u003Cspan class=\"hljs-params\">(String[] args)\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">throws\u003C\u002Fspan> InterruptedException {\n        \u003Cspan class=\"hljs-type\">Thread\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">t1\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Thread\u003C\u002Fspan>(() -&gt; { sharedBuilder.append(\u003Cspan class=\"hljs-string\">&quot;Thread1 &quot;\u003C\u002Fspan>); });\n        \u003Cspan class=\"hljs-type\">Thread\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">t2\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Thread\u003C\u002Fspan>(() -&gt; -&gt; { sharedBuilder.append(\u003Cspan class=\"hljs-string\">&quot;Thread2 &quot;\u003C\u002Fspan>); });\n\n        t1.start();\n        t2.start();\n        t1.join();\n        t2.join();\n\n        System.out.println(sharedBuilder.toString()); \u003Cspan class=\"hljs-comment\">\u002F\u002F 输出结果可能不一致或不完整\u003C\u002Fspan>\n    }\n}\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003Cp data-line=\"144\">\u003Cstrong>问题\u003C\u002Fstrong>：多个线程同时操作非线程安全的 \u003Ccode>StringBuilder\u003C\u002Fcode>，可能导致数据丢失、脏读或异常。\u003C\u002Fp>\n\u003Ch4 data-line=\"146\" id=\"✅ 正确代码（视情况而定）\">✅ 正确代码（视情况而定）\u003C\u002Fh4>\n\u003Col data-line=\"147\">\n\u003Cli data-line=\"147\">\u003Cstrong>使用 StringBuffer\u003C\u002Fstrong>（推荐）：\n        \u003Cdetails  data-line=\"148\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-type\">StringBuffer\u003C\u002Fspan> \u003Cspan class=\"hljs-variable\">sharedBuffer\u003C\u002Fspan> \u003Cspan class=\"hljs-operator\">=\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">StringBuffer\u003C\u002Fspan>(); \u003Cspan class=\"hljs-comment\">\u002F\u002F 线程安全\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003Cli data-line=\"151\">\u003Cstrong>使用线程隔离\u003C\u002Fstrong>（每个线程使用自己的 \u003Ccode>StringBuilder\u003C\u002Fcode>）：\n        \u003Cdetails  data-line=\"152\" class=\"md-editor-code\" open=\"\">\n          \u003Csummary class=\"md-editor-code-head\">\n            \u003Cdiv class=\"md-editor-code-flag\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cdiv class=\"md-editor-code-action\">\n              \u003Cspan class=\"md-editor-code-lang\">java\u003C\u002Fspan>\n              \u003Cspan class=\"md-editor-copy-button\" data-tips=\"复制代码\">复制代码\u003C\u002Fspan>\n              \n              \u003Cspan class=\"md-editor-collapse-tips\">\u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"lucide lucide-circle-chevron-left md-editor-icon\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"m14 16-4-4 4-4\"\u002F>\u003C\u002Fsvg>\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n          \u003C\u002Fsummary>\n          \u003Cpre>\u003Ccode class=\"language-java\" language=java>\u003Cspan class=\"md-editor-code-block\">\u003Cspan class=\"hljs-keyword\">private\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">static\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">final\u003C\u002Fspan> ThreadLocal&lt;StringBuilder&gt; localBuilder = ThreadLocal.withInitial(StringBuilder::\u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan>);\n\u003Cspan class=\"hljs-comment\">\u002F\u002F 在每个线程内部调用 localBuilder.get().append(...)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan rn-wrapper aria-hidden=\"true\">\u003Cspan>\u003C\u002Fspan>\u003Cspan>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\n        \u003C\u002Fdetails>\n      \u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 data-line=\"157\" id=\"4 实战技巧与最佳实践\">4 实战技巧与最佳实践\u003C\u002Fh2>\n\u003Col data-line=\"159\">\n\u003Cli data-line=\"159\">\n\u003Cp data-line=\"159\">\u003Cstrong>选型口诀\u003C\u002Fstrong>：\u003C\u002Fp>\n\u003Cul data-line=\"160\">\n\u003Cli data-line=\"160\">\u003Cstrong>内容不变用 String\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli data-line=\"161\">\u003Cstrong>单线程拼接用 StringBuilder\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli data-line=\"162\">\u003Cstrong>多线程拼接用 StringBuffer\u003C\u002Fstrong>\u003C\u002Fli>\n\u003Cli data-line=\"163\">\u003Cstrong>循环拼接，绝不用 String！\u003C\u002Fstrong>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003C\u002Fli>\n\u003Cli data-line=\"165\">\n\u003Cp data-line=\"165\">\u003Cstrong>简单拼接优化\u003C\u002Fstrong>：对于一次性拼接少量字符串（如 \u003Ccode>&quot;Hello, &quot; + name\u003C\u002Fcode>），现代Java编译器（JDK5+）会自动优化为 \u003Ccode>StringBuilder\u003C\u002Fcode> 操作，这种情况下直接使用 \u003Ccode>+\u003C\u002Fcode> 可读性更好，无需刻意创建 \u003Ccode>StringBuilder\u003C\u002Fcode>。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli data-line=\"167\">\n\u003Cp data-line=\"167\">\u003Cstrong>API高效使用\u003C\u002Fstrong>：熟练使用 \u003Ccode>append()\u003C\u002Fcode>, \u003Ccode>insert()\u003C\u002Fcode>, \u003Ccode>delete()\u003C\u002Fcode>, \u003Ccode>reverse()\u003C\u002Fcode> 等方法，可以更灵活地操作字符串。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 data-line=\"169\" id=\"总结\">总结\u003C\u002Fh2>\n\u003Cp data-line=\"171\">理解 \u003Ccode>String\u003C\u002Fcode>、\u003Ccode>StringBuilder\u003C\u002Fcode> 和 \u003Ccode>StringBuffer\u003C\u002Fcode> 的本质区别是写出高效、健壮Java程序的关键。请记住这个核心原则：\u003Cstrong>根据字符串的“变化频率”和代码的“线程环境”来做出选择\u003C\u002Fstrong>。在大多数现代应用中，由于多数代码运行在单线程上下文（如Web请求的处理），\u003Ccode>StringBuilder\u003C\u002Fcode> 成为了最常用的选择。\u003C\u002Fp>\n\u003Cp data-line=\"173\">希望这份详细的指南能帮助你在实际开发中做出正确的选择。\u003C\u002Fp>\n",4337,14,"0","",2,0,15,"StringBuilder,线,String,代码,字符串","\n在Java开发中，String、StringBuffer和StringBuilder是处理文本的核心类。选择不当会引发性能问题和线程安全隐患。下面通过对比介绍和代码示例，帮助你精准选用。\n\n1 核心特性对比\n下面的表格直观对比了这三个类的核心差异，方便您快速把握重点。","2025-12-22 15:31:14"]