在 Java 中,String 被设计为不可变(immutable),主要有以下几方面原因(既和语言设计有关,也和实现机制有关):
不可变指的是:
一旦 String 对象被创建,它里面的字符内容就不能被修改。
任何“修改”操作(如 substring、replace、concat)都会创建一个新的 String 对象,而不是改原对象。
String s = "abc";
s = s + "d"; // 实际是创建了新对象 "abcd"
Java 为了节省内存,使用了 字符串常量池:
String a = "abc";
String b = "abc";
// a 和 b 指向同一个对象
如果 String 可变:
a改变 -> b也被改变
这会引发严重的逻辑错误,所以必须不可变。
不可变对象:
String s = "hello";
// 多线程同时使用 s,不会有问题
如果可变,就需要额外的同步控制。
String 常被用作 HashMap 的 key。
public int hashCode() {
// 只计算一次并缓存
}
因为不可变:
hashCode 永远不变如果可变,作为 key 时会导致哈希混乱。
很多核心 API 都依赖 String:
例如:
File file = new File("/data/a.txt");
如果 String 可变,攻击者可能在传递过程中修改路径,造成安全问题。
JVM 在加载类时:
Class.forName("com.xxx.Test")
如果类名字符串可变,类加载器会变得非常不安全。
在 JDK 源码中(简化):
public final class String {
private final char value[]; // JDK 8 及以前
// 或
private final byte value[]; // JDK 9 以后
}
关键点:
final class:不能被继承private final value[]:外部无法修改String s = "a";
s += "b";
实际过程是:
"a""ab"s 指向新对象✅ 对象没变
❌ 变量引用变了
Java 也提供了可变方案:
StringBuilder
StringBuffer(线程安全)
适合大量拼接场景。
Java 的 String 不可变,是为了安全性、性能、线程安全和字符串池机制,这是 Java 语言设计上的核心权衡。
如果你愿意,我也可以:
String / StringBuilder免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。