Java中String不可变性指对象内容创建后不可修改,所有操作均生成新对象;字符串字面量自动复用常量池,而new String()强制堆新建;拼接应避免+,改用StringBuilder。

Java 中 String 的不可变性不是“不能改变量名”,而是对象内容一旦创建就锁死,任何看似修改的操作(如拼接、替换、转大写)都会生成新对象。理解这点是避免内存浪费的关键——真正浪费的不是“不可变”本身,而是没意识到它在哪儿悄悄造新对象。
字符串字面量优先复用常量池
直接用双引号赋值("abc")会触发 JVM 检查字符串常量池:已有就复用,没有才新建。这天然节省堆内存。
- ✅ 推荐:
String a = "config"; String b = "config";→a == b为true,共用一个对象 - ❌ 避免:
String c = new String("config");→ 强制在堆上新建对象,即使常量池里已有,还多一次拷贝
拼接大量字符串别用 + 或 +=
在循环或高频场景中,用 + 拼接多个字符串,每次都会创建新 String 对象,旧对象很快变成垃圾,GC 压力大。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。
- ⚠️ 问题代码:
String s = ""; for (int i = 0; i → 创建约 1000 个中间 String 对象 - ✅ 正确做法:改用
StringBuilder(单线程)或StringBuffer(多线程),它们内部用可变 char/byte 数组,只在最终调用toString()时才生成一个 String
谨慎使用 substring(尤其老 JDK 版本)
Java 7u6 之前,substring 不复制字符数组,只是共享原 value[] 并调整 offset/length。如果原字符串很大(比如读了 10MB 文件),而你只取其中 10 个字符,这个小字符串仍持有对整个大数组的引用,导致大数组无法回收。
- ✅ 现代 JDK(7u6+ 及所有 JDK 8/9+)已修复:
substring默认做数组拷贝,安全但略慢;若确定原字符串很快失效,可用new String(str.substring(...))显式触发拷贝(不过通常没必要) - ? 提示:读取长文本后提取短字段时,直接用
String.valueOf(chars, start, len)或构造新 String 更可控
敏感操作前先判断是否真需要新对象
很多方法如 trim()、toLowerCase()、replace() 都可能返回新对象。但如果原字符串已经满足条件,这些方法会直接返回 this(JDK 优化过)。
- ✅ 可以放心用:
s.trim()—— 若首尾无空格,不创建新对象 - ⚠️ 但不要假设:
s.replace("a", "b")即使没匹配到,也返回新对象(JDK 实现决定,非 always this) - ? 小技巧:对固定字符串做转换,优先用常量池中的结果,例如预定义
public static final String EMPTY_UPPER = "";而非每次调用"".toUpperCase()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










