前言
在 Java 学习中,String 字符串是日常编码使用频率最高的类。我们经常做字符串定义、拼接、内容比较,但大多数初学者只会调用方法,不了解底层源码原理。本文基于 JDK8 源码,用简单通俗的语言讲解 String 底层结构、不可变性、常用方法和字符串常量池,适合 Java 入门学习和课程作业使用。
一、String 底层源码结构
- 类定义
java
public final class String
implements Serializable, Comparable<String>, CharSequence
String 被 final 修饰,不能被继承,避免子类篡改底层逻辑。同时实现三个接口:支持对象序列化、字符串字典比较排序、字符序列统一规范。
- 核心成员变量
java
private final char[] value;
private int hash;
- char[] value :底层真正存放字符串内容的字符数组,例如 "java" 底层就是 ['j','a','v','a'] ;
- private :外部无法直接访问和修改底层数组;
- final :数组引用地址不可更改;
- hash :缓存哈希值,避免重复计算,提升查找和比较效率。
二、String 的不可变性
String 最核心的特性是不可变:字符串一旦创建完成,底层字符内容就不能被修改。
不可变的四层保障
1. 类被 final 修饰,无法被继承重写;
2. 底层字符数组 value 被 private 封装,外部无法访问;
3. value 用 final 修饰,数组引用地址不能改变;
4. String 没有提供任何修改底层数组的方法,所有操作都会生成新对象。
常见误区
java
String s = "hello";
s = s + "world";
并不是修改原字符串,而是生成一个全新的字符串对象,原来的字符串始终没有变化。
三、常用核心方法简析
- equals() 方法
作用:比较两个字符串的实际内容是否相同。
底层逻辑:先判断内存地址,再校验类型,最后逐一个字符对比内容。
- == 与 equals() 区别
- == :比较对象的内存地址;
- equals() :比较字符串的具体内容。
开发中比较字符串内容,一定要用 equals() 。
四、字符串常量池
Java 为了节省内存,设计了字符串常量池:
1. 双引号直接定义的字符串,会存入常量池,重复定义自动复用,不重复创建对象;
2. new String("abc") 会在堆内存新建对象,不会复用常量池;
3. 开发建议:优先使用字面量方式定义字符串,节省内存开销。
五、初学者编码规范
1. 字符串内容比较一律使用 equals() ,禁止用 == ;
2. 循环里不要用 + 拼接字符串,会频繁创建新对象,效率低下,推荐使用 StringBuilder ;
3. 充分理解 String 不可变性,不要尝试修改原有字符串,拼接操作使用工具类。
六、总结
String 底层本质是字符数组,通过 final 修饰和封装特性实现了不可变性,配合字符串常量池优化内存使用。弄懂 String 源码基础原理,不仅能夯实 Java 入门功底,规避日常编码错误,还能为后续集合、JVM 进阶学习打好基础。
