这个标题一看就是冲着面试 + 深入理解去的,那我就按
“源码结构 → 设计思想 → 关键方法 → 易错点 → 面试总结”
帮你把 Java String 源码一篇讲透 👇
说明:以下基于 JDK 8(JDK 9+ 有压缩字符串差异,我后面会单独点)
一、String 是什么?
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
关键信息
final:不可被继承- 实现接口:
Serializable(可序列化)Comparable(可比较)CharSequence(字符序列)
👉 设计目标:
安全、不可变、可复用、线程安全
二、String 的底层数据结构
1️⃣ JDK 8 之前(含 JDK 8)
private final char[] value;
- 使用
char数组 - 每个
char占 2 字节(UTF-16)
2️⃣ JDK 9+(了解)
private final byte[] value;
private final byte coder;
LATIN1(1 字节)UTF16(2 字节)- 节省内存(压缩字符串)
三、String 为什么是不可变的?
源码核心:
private final char[] value;
不可变的三个关键点
value是final- 没有提供修改内部数组的方法
- 所有“修改”操作都会 new 新对象
String s = "abc";
s = s.concat("d"); // 新对象
不可变的好处
✅ 线程安全
✅ 可缓存 hashCode
✅ 适合做 Map 的 key
✅ 字符串常量池可复用
四、String 的构造方法源码要点
1️⃣ 使用字面量
String s = "abc";
- 放入 字符串常量池
- 相同字面量只创建一个对象
2️⃣ new String()
String s = new String("abc");
- 堆中一个新对象
- 常量池中仍然有
"abc"
👉 一共两个对象
五、equals() 与 == 的区别(源码级)
equals 源码核心
public boolean equals(Object anObject) {
if (this == anObject) return true;
if (anObject instanceof String) {
String aString = (String) anObject;
if (value.length == aString.value.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != aString.value[i]) {
return false;
}
}
return true;
}
}
return false;
}
👉 逐字符比较内容
== 比较的是?
- 对象引用地址
六、hashCode() 为什么只算一次?
private int hash; // 默认 0
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
for (char c : value) {
h = 31 * h + c;
}
hash = h;
}
return h;
}
设计点
- 懒加载
- 只算一次,后续直接返回
- 不可变 → hash 永远不变
七、String + 拼接的底层原理
1️⃣ 常量拼接(编译期)
String s = "a" + "b";
⬇ 编译后
String s = "ab";
2️⃣ 变量拼接(运行期)
String s = a + b;
⬇ 实际是
new StringBuilder()
.append(a)
.append(b)
.toString();
👉 循环拼接字符串要用 StringBuilder
八、String.intern() 原理
String s = new String("abc");
s.intern();
- JDK 7+:
- 常量池存的是 堆中对象引用
- 如果池中没有:
- 放入当前对象引用
- 如果有:
- 返回池中引用
九、String / StringBuilder / StringBuffer
| 类 | 可变 | 线程安全 | 性能 |
|---|---|---|---|
| String | ❌ | ✅ | 低 |
| StringBuilder | ✅ | ❌ | 高 |
| StringBuffer | ✅ | ✅ | 中 |
十、面试高频坑点总结
❗ 1. String 为什么是 final?
- 防止被继承破坏不可变性
❗ 2. String 真的不可变吗?
- 引用可变,对象内容不可变
❗ 3. String 做 HashMap key 为什么安全?
- hash 不变
- equals 稳定
十一、一句话终极总结(面试必背)
String 是一个不可变的、基于字符数组实现的类,通过常量池实现复用,hashCode 缓存提升性能,字符串拼接底层依赖 StringBuilder。
如果你愿意,我可以继续给你:
- 🔥 JDK 9 String 压缩字符串源码
- 🔥 String.intern() 面试追问
- 🔥 字符串常量池 + JVM 内存结构
- 🔥 String 面试题 20 连击
你是 准备 Java 面试,还是 深入看 JDK 源码?