news 2026/7/12 7:01:23

HoRain云--Java String类:不可变设计的深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HoRain云--Java String类:不可变设计的深度解析

🎬 HoRain云小助手:个人主页

🔥 个人专栏: 《Linux 系列教程》《c语言教程》

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

☕ Java String类:不可变的那点事

🎯 先立骨架:String 是什么

🧱 创建方式:两种路径,内存位置不同

常量池是怎么回事

⚖️ ==vs equalsvs compareTo

🔤 常用 API(挑高频)

🏗️ 拼接:+vs StringBuildervs StringBuffer

+号在循环里是性能杀手

StringBuildervs StringBuffer

🧬 不可变的好处(为什么 Java 这么设计)

🔍 几个高频追问点

1)String s = null;vs ""

2)switch能用 String(Java 7+)

3)String.format

4)intern()什么时候用

🧮 编码相关(历史包袱)

🆕 JDK 9 之后两个变动(面试爱问)

🎯 一张表收尾


☕ JavaString类:不可变的那点事

String是 Java 里最特殊也最常被追问的类——看似简单,牵扯到不可变设计、常量池、编码演进、拼接性能一堆东西。

🎯 先立骨架:String 是什么

public final class String implements Serializable, Comparable<String>, CharSequence

三个关键事实:


🧱 创建方式:两种路径,内存位置不同

// 1. 字面量 → 常量池(String Pool) String s1 = "hello"; // 2. new → 堆里新对象(顺带常量池放一份,但不保证) String s2 = new String("hello");

常量池是怎么回事

String a = "hello"; String b = "hello"; System.out.println(a == b); // true,同一池对象 String c = new String("hello"); String d = new String("hello"); System.out.println(c == d); // false,不同堆对象 System.out.println(c.equals(d)); // true,值相等 // intern():拉到池里,池里有就返回池对象 String e = new String("hello").intern(); System.out.println(a == e); // true

💡new String("hello")最坏情况会创建 2 个对象:池里一份(如果之前没出现过)+ 堆里一份。所以日常没必要new String("xxx")


⚖️==vsequalsvscompareTo

String s1 = new String("abc"); String s2 = new String("abc"); s1 == s2 // false,比地址 s1.equals(s2) // true,比值(先比地址,再比长度,再逐 char) s1.equalsIgnoreCase("ABC") // true,忽略大小写 // 比大小 / 排序 "abc".compareTo("abd") // -1(按字典序,Unicode 值) "Abc".compareToIgnoreCase("abc") // 0

⚠️equalsnull返回falseObjects.equals(s1, s2)更安全(俩都 null 也返回 true)。


🔤 常用 API(挑高频)

String s = " Hello, 世界 "; s.length(); // 9(char 数,注意不是字节数) s.charAt(1); // 'H' s.trim(); // "Hello, 世界"(去首尾空白,Unicode 空白不全) s.strip(); // "Hello, 世界"(Java 11+,按 Unicode 空白,更准) s.stripLeading(); s.stripTrailing(); s.toLowerCase(); s.toUpperCase(); s.startsWith(" He"); // true s.endsWith(" "); // true s.substring(2, 7); // "Hello"(左闭右开) s.replace("l", "L"); // " HeLLo, 世界 " s.replaceAll("\\s+", ""); // 正则替换:"Hello,世界"(中间逗号还在) String[] parts = s.split(","); // [" Hello", " 世界 "] String.join("-", "a", "b", "c"); // "a-b-c" // 判空(Java 11+) s.isEmpty(); // false s.isBlank(); // false(" " → true,比 isEmpty 多认空白)

🏗️ 拼接:+vsStringBuildervsStringBuffer

+号在循环里是性能杀手

// ❌ 每次循环 new 一个 StringBuilder + toString(),O(n²) String s = ""; for (int i = 0; i < 10000; i++) { s += i; // 等效:s = new StringBuilder(s).append(i).toString(); } // ✅ 一次 StringBuilder,O(n) StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb.append(i); } String s = sb.toString();

📌 单条"a" + "b" + "c"编译器(javac)已经在编译期合并成"abc"(常量折叠),或多条非循环拼接也会帮你包一层StringBuilder——只有循环里的+才是真坑

StringBuildervsStringBuffer

线程安全

性能

场景

StringBuilder

❌ 不同步

单线程(99% 场景)

StringBuffer

synchronized

慢点

多线程共享(少见)


🧬 不可变的好处(为什么 Java 这么设计)

  1. 线程安全:天然不可变,随便传

  2. 常量池复用:省内存

  3. hash 可缓存hashCode()算一次存起来(看源码hash字段)

  4. 安全:类加载器用 String 当类名/路径,不可变防篡改

代价:频繁修改产生大量中间对象 → 所以用StringBuilder


🔍 几个高频追问点

1)String s = null;vs""

String a = null; // 没对象,调 a.length() → NPE String b = ""; // 有对象,长度 0

2)switch能用 String(Java 7+)

switch (s) { case "hello" -> System.out.println("hi"); case "world" -> System.out.println("earth"); default -> {} }

原理:编译期转成hashCode() + equals的 if-else,不是 JVM 层面支持的。

3)String.format

String s = String.format("name=%s, age=%d, pi=%.2f", "Alice", 30, Math.PI); // "name=Alice, age=30, pi=3.14"

4)intern()什么时候用

几乎不用。只有在你从别处(网络/文件)读了一堆重复字符串、想手动挤到池里省内存时才考虑:

String s = readFromNet(); // 可能重复百万个 s = s.intern(); // 池里复用

代价:池在 Perm/Metaspace,早期 JDK 容易 OOM,现在没那么脆,但仍别滥用。


🧮 编码相关(历史包袱)

// char 是 UTF-16,一个 char ≠ 一个"字" String s = "😀"; // emoji,占 2 个 char(代理对) System.out.println(s.length()); // 2(char 数) System.out.println(s.codePointCount(0, s.length())); // 1(真正的"字形"数) // 字节 ↔ 字符 byte[] utf8 = s.getBytes(StandardCharsets.UTF_8); // 指定编码,别用无参(跟平台走) String back = new String(utf8, StandardCharsets.UTF_8);

⚠️ 无参getBytes()平台默认编码,Windows 中文环境曾默认 GBK,跨环境就炸——永远显式传Charset


🆕 JDK 9 之后两个变动(面试爱问)

  1. char[]byte[] + coder

  2. String拼接在 javac 层


🎯 一张表收尾

问题

答案

String 可变吗

❌ final + private final byte[]

"a"+"b"创建了几个对象

编译期折成"ab",只进常量池 1 个

new String("a")几个

池 1 + 堆 1(池已有时堆 1)

循环拼接用啥

StringBuilder

==vsequals

地址 vs 值

为什么不可变

线程安全 / 池复用 / hash 缓存 / 安全

char 能表示所有 Unicode 吗

❌,增补字符(emoji)要俩 char

要不要接着看StringBuilder源码那点事,或者StringStringBuilderStringBuffer的面试连招题?

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 4:13:26

SAP服务供应商选型指南:六大评估维度与四步筛选流程

在数字化转型进入深水区的今天&#xff0c;SAP作为企业资源规划&#xff08;ERP&#xff09;领域的核心解决方案&#xff0c;其实施落地的专业性直接决定企业转型的成败。尤其2026年以来&#xff0c;面对SAP ECC系统停止更新的关键窗口期&#xff0c;云化迁移、系统整合成为行业…

作者头像 李华
网站建设 2026/7/11 2:18:09

AI-提效模板之--SKILL.md

. Skills 以 MarkDown 文本载体存储&#xff0c;本身不直接执行功能。4. Skills 的核心就是&#xff1a;一个文件夹 一个 SKILL.md 文件--必需。 (也可以有其他文件夹&#xff0c;如 references/# 可选&#xff1a;参考文档, assets/# 可选&#xff1a;模板、资源)for-example…

作者头像 李华
网站建设 2026/7/11 6:23:38

Adobe Speech to Text 使用教程Adobe Speech to Text 2026 Mac 下载安装教程

文章目录前言Adobe Speech to Text 2026 下载地址Adobe Speech to Text 2026 安装教程Adobe Speech to Text 2026 Mac 新手入门指南&#xff1a;从安装到第一个项目前言 如果你正在寻找一款能在 Mac 上流畅运行的专业语音转文字工具&#xff0c;Adobe Speech to Text 2026 绝对…

作者头像 李华
网站建设 2026/7/10 15:03:54

深入理解CSRF攻击:原理、复现与全面防御实践指南

1. 项目概述&#xff1a;从一次“被点赞”说起几年前&#xff0c;我在一个技术社区里发了个帖子&#xff0c;吐槽某个开源库的文档写得实在太烂。帖子发出去没多久&#xff0c;就收到了一堆点赞和“1”的回复&#xff0c;心里还挺美&#xff0c;觉得找到了共鸣。结果第二天登录…

作者头像 李华