Java 字符串(String)核心知识点总结(JDK8)
一、String 基础特性
- String 是 final 类 :不可被继承,底层由
final char[]存储(JDK9 改为 byte[])。 - 不可变性 :字符串一旦创建,内容无法修改 。
- 所有修改操作(截取、替换、拼接)都会返回新字符串。
- 好处:线程安全、常量池复用、哈希值固定。
二、字符串常量池(String Pool)
- 位置 :JDK8 中位于堆内存中。
- 作用:缓存字符串字面量,实现对象复用,节省内存。
- 核心规则 :
- 相同内容的字符串,常量池中只存一份。
- 使用字面量创建的字符串,自动进入常量池。
三、三种创建方式的内存区别
1. 字面量创建(推荐)
java
String s = "hello";
- 先查常量池,存在直接复用,不存在则创建。
- 只在常量池创建 1 个对象。
2. new String 创建
java
String s = new String("hello");
- 常量池中创建/复用
"hello"。 - 堆中创建新的 String 对象。
- 共创建 2 个对象(堆1个 + 常量池1个)。
3. 字符串拼接
-
常量 + 常量 (
"a" + "b")
编译期直接优化为"ab",存入常量池。 -
变量 + 变量/常量 (
a + b)
底层优化为:javanew StringBuilder().append(a).append(b).toString()最终在堆中创建新对象 ,不进入常量池。
四、intern() 方法详解
1. 作用
手动将字符串加入常量池,并返回常量池中的对象引用。
2. 执行逻辑
- 去常量池查找相同内容的字符串。
- 存在 → 直接返回常量池对象。
- 不存在 → 将当前对象的引用存入常量池,再返回。
3. 关键点
- 不会删除/移动原堆对象。
- 原对象无引用时,由 GC 自动回收。
- 目的:实现字符串复用,节省内存,可用
==快速比较。
五、== 和 equals() 区别
==- 基本类型:比较值。
- 引用类型(String):比较内存地址。
equals()- String 重写了该方法,比较字符串内容。
- 开发规范:字符串比较必须用 equals() (常量池复用可用
==,但不推荐)。
六、经典内存面试题
题1
java
String s1 = "abc";
String s2 = "abc";
// s1 == s2 → true(常量池复用同一对象)
题2
java
String s1 = new String("abc");
String s2 = new String("abc");
// s1 == s2 → false(两个不同堆对象)
题3
java
String s1 = "ab";
String s2 = "a" + "b";
String s3 = s1 + "b";
// s1 == s2 → true(编译优化)
// s1 == s3 → false(s3 在堆中)
题4
java
String s1 = new String("hello");
String s2 = s1.intern();
String s3 = "hello";
// s1 == s2 → false
// s2 == s3 → true
七、核心总结(必背)
- String 不可变,修改返回新对象。
- 字面量存常量池,
new String()存堆内存。 - 变量拼接底层用
StringBuilder,结果在堆。 intern()手动入池,返回常量池对象,不删除原对象。- 字符串比较用
equals(),地址比较用==。