在 Java 中,字符串(String)被设计为不可变(immutable),这是由 JDK 设计者有意决定的,背后有多方面的原因。下面从定义、实现机制、优点、示例几个角度系统说明。
不可变意味着:
一个 String 对象一旦被创建,它的值(字符序列)就不能被修改。
String s = "abc";
s = s + "d";
这里发生了什么?
"abcd""abc" 仍然存在(如果没有被引用,就等待 GC)Java 为了节省内存,设计了 字符串常量池。
String a = "abc";
String b = "abc";
a 和 b 指向同一个对象a 会影响 b,这是灾难性的✅ 不可变保证了字符串共享的安全性
因为 String 不能被修改,所以:
这是 String 在多线程环境中天然安全的重要原因。
String 经常被用作 HashMap 的 key。
@Override
public int hashCode() {
if (hash == 0) {
hash = computeHash();
}
return hash;
}
hash 值在第一次计算后缓存hashCode() 一定相同✅ 提高 HashMap / HashSet 性能
字符串广泛用于:
Class.forName("java.lang.String"))如果 String 可变:
String filename = "/etc/passwd";
// 某个方法偷偷修改了 filename
可能引发严重安全问题。
✅ 不可变避免被篡改
不可变对象:
以 JDK 8 为例:
public final class String
implements Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // 缓存哈希值
}
关键点:
| 特性 | 作用 |
|---|---|
final class |
不能被继承 |
private final char[] value |
外部无法直接修改 |
| 不提供修改方法 | 没有 setCharAt() |
⚠️ 注意:
value 是 final 的引用String s = "a";
s = s + "b";
等价于(简化):
new StringBuilder()
.append("a")
.append("b")
.toString();
✅ 每次“修改”都会生成新对象
✅ 原对象不变
因为频繁修改字符串时:
String s = "";
for (int i = 0; i < 10000; i++) {
s += i; // 每次都创建新对象
}
性能极差 ❌
✅ 正确做法:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
String result = sb.toString();
Java 中 String 不可变,是为了安全性、线程安全、字符串共享、哈希缓存和性能优化而设计的。
如果你愿意,我也可以:
String vs StringBuilder vs StringBuffer免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。