【Java】一文搞懂String源码

这个标题一看就是冲着面试 + 深入理解去的,那我就按
“源码结构 → 设计思想 → 关键方法 → 易错点 → 面试总结”
帮你把 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;

不可变的三个关键点

  1. value 是 final
  2. 没有提供修改内部数组的方法
  3. 所有“修改”操作都会 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 源码

文章已创建 4298

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部