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 这么设计 几个高频追问点1String s null;vs 2switch能用 StringJava 73String.format4intern()什么时候用 编码相关历史包袱 JDK 9 之后两个变动面试爱问 一张表收尾☕ JavaString类不可变的那点事String是 Java 里最特殊也最常被追问的类——看似简单牵扯到不可变设计、常量池、编码演进、拼接性能一堆东西。 先立骨架String 是什么public final class String implements Serializable, ComparableString, CharSequence三个关键事实final类不能被继承不可变immutable值存在private final byte[] value里外部改不了char[] → byte[]JDK 9从每个 char 2 字节 UTF-16改成byte[] coder 标志拉丁文省一半内存 创建方式两种路径内存位置不同// 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); // truenew String(hello)最坏情况会创建 2 个对象池里一份如果之前没出现过 堆里一份。所以日常没必要new String(xxx)。⚖️vsequalsvscompareToString 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⚠️equals传null返回falseObjects.equals(s1, s2)更安全俩都 null 也返回 true。 常用 API挑高频String s Hello, 世界 ; s.length(); // 9char 数注意不是字节数 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(); } // ✅ 一次 StringBuilderO(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 这么设计线程安全天然不可变随便传常量池复用省内存hash 可缓存hashCode()算一次存起来看源码hash字段安全类加载器用 String 当类名/路径不可变防篡改代价频繁修改产生大量中间对象 → 所以用StringBuilder。 几个高频追问点1String s null;vsString a null; // 没对象调 a.length() → NPE String b ; // 有对象长度 02switch能用 StringJava 7switch (s) { case hello - System.out.println(hi); case world - System.out.println(earth); default - {} }原理编译期转成hashCode() equals的 if-else不是 JVM 层面支持的。3String.formatString s String.format(name%s, age%d, pi%.2f, Alice, 30, Math.PI); // nameAlice, age30, pi3.144intern()什么时候用几乎不用。只有在你从别处网络/文件读了一堆重复字符串、想手动挤到池里省内存时才考虑String s readFromNet(); // 可能重复百万个 s s.intern(); // 池里复用代价池在 Perm/Metaspace早期 JDK 容易 OOM现在没那么脆但仍别滥用。 编码相关历史包袱// char 是 UTF-16一个 char ≠ 一个字 String s ; // emoji占 2 个 char代理对 System.out.println(s.length()); // 2char 数 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 之后两个变动面试爱问char[]→byte[] coderLATIN11 字节存一个 charUTF162 字节纯英文字符串内存直接砍半String拼接在 javac 层单条 / 非循环多段→ 编译期直接StringBuilder或常量折叠循环里仍每轮 new → 自己写StringBuilder 一张表收尾问题答案String 可变吗❌ final private final byte[]ab创建了几个对象编译期折成ab只进常量池 1 个new String(a)几个池 1 堆 1池已有时堆 1循环拼接用啥StringBuildervsequals地址 vs 值为什么不可变线程安全 / 池复用 / hash 缓存 / 安全char 能表示所有 Unicode 吗❌增补字符emoji要俩 char要不要接着看StringBuilder源码那点事或者String、StringBuilder、StringBuffer的面试连招题❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧