Java 中的 String 不是基本类型,而是引用类型。

(图片来源网络,侵删)
这是一个必须牢记的重要知识点,Java 的设计者将数据类型分为两大类:基本类型和引用类型。
Java 的基本类型
Java 语言定义了 8 种基本数据类型,它们是 Java 语言最基础的组成单元,用于定义简单的变量,它们的特点是:
- 值存储在栈内存中:变量的值直接存储在变量所在的内存空间里。
- 效率高:因为数据结构简单,直接操作值,所以速度很快。
- 没有方法:基本类型本身不具备任何行为(方法),它们只是纯粹的值。
- 大小固定:每种基本类型都有固定的大小,不随平台变化。
这 8 种基本类型可以分为四类:
| 类型 | 大小 (字节) | 默认值 | 包装类 | 描述 |
|---|---|---|---|---|
byte |
1 | 0 | Byte |
8位有符号整数 |
short |
2 | 0 | Short |
16位有符号整数 |
int |
4 | 0 | Integer |
32位有符号整数 |
long |
8 | 0L | Long |
64位有符号整数 |
float |
4 | 0f | Float |
32位单精度浮点数 |
double |
8 | 0d | Double |
64位双精度浮点数 |
char |
2 | '\u0000' | Character |
16位 Unicode 字符 |
boolean |
(理论1) | false | Boolean |
表示真或假 |
关键点:String 不在这个列表里。

(图片来源网络,侵删)
String 是引用类型
既然 String 不是基本类型,那它就是引用类型,引用类型的特点是:
- 存储的是对象的内存地址(引用):变量本身不直接存储对象的数据,而是存储了指向该对象在堆内存中实际位置的地址。
- 数据存储在堆内存中:对象(如
String对象)及其数据存储在堆内存中。 - 可以调用方法:因为
String是一个类,所以它的实例(对象)可以调用类中定义的方法,如.length(),.substring(),.equals()等。 - 默认值为
null:引用类型变量的默认值是null,表示它没有指向任何有效的对象。
String 的特殊之处
String 在 Java 中是一个非常特殊的引用类型,它有一些独特的性质,这些性质有时会让人误以为它是基本类型:
-
不可变性
String对象一旦被创建,其内容(内部的字符数组)就不能被修改。- 当你像这样操作时:
String s = "hello"; s = "world";,你并没有修改原来的"hello"对象,而是创建了一个新的"world"对象,然后让引用变量s指向了这个新对象,原来的"hello"对象如果没有其他引用指向它,就会被垃圾回收器回收。 - 这种设计带来了线程安全和性能优化(例如字符串常量池)。
-
字面量语法
(图片来源网络,侵删)- 你可以使用双引号 来直接创建一个
String对象,如String str = "abc";,这种语法非常方便,看起来像是在使用基本类型。 - 编译器会自动处理这个语法,它会在堆内存(或字符串常量池)中创建一个
String对象。
- 你可以使用双引号 来直接创建一个
-
字符串常量池
- 为了提高性能和减少内存开销,Java 使用了一个特殊的内存区域——字符串常量池。
- 当你使用字面量
String s = "abc";创建字符串时,JVM 首先会检查常量池中是否已经存在"abc"这个字符串,如果存在,就直接返回该对象的引用;如果不存在,就创建一个新的并放入池中。 - 这与通过
new关键字创建字符串不同:String s = new String("abc");会强制在堆上创建一个新的对象,即使常量池中已经存在"abc"。
如何区分: 与 equals()
这是理解 String 作为引用类型最关键的实践点。
-
操作符:
- 对于基本类型: 比较的是值是否相等。
- 对于引用类型: 比较的是两个引用变量是否指向同一个内存地址(即是否是同一个对象)。
-
equals()方法:- 对于引用类型,
equals()方法通常用于比较两个对象的内容(逻辑上)是否相等。 String类重写了Object类的equals()方法,专门用于比较两个字符串的字符序列是否完全相同。
- 对于引用类型,
示例代码
public class StringComparison {
public static void main(String[] args) {
// 情况1:使用字面量创建,指向常量池中的同一个对象
String s1 = "hello";
String s2 = "hello";
System.out.println("s1 == s2: " + (s1 == s2)); // true (地址相同)
System.out.println("s1.equals(s2): " + s1.equals(s2)); // true (内容相同)
System.out.println("--------------------");
// 情况2:使用 new 关键字创建,在堆上创建新对象
String s3 = new String("world");
String s4 = new String("world");
System.out.println("s3 == s4: " + (s3 == s4)); // false (地址不同,是两个不同的对象)
System.out.println("s3.equals(s4): " + s3.equals(s4)); // true (内容相同)
System.out.println("--------------------");
// 情况3:混合比较
String s5 = "java";
String s6 = new String("java");
System.out.println("s5 == s6: " + (s5 == s6)); // false (一个指向常量池,一个指向堆)
System.out.println("s5.equals(s6): " + s5.equals(s6)); // true (内容相同)
System.out.println("--------------------");
// 情况4:基本类型比较
int a = 10;
int b = 10;
System.out.println("a == b: " + (a == b)); // true (值相同)
}
}
| 特性 | 基本类型 | 引用类型 (以 String 为例) |
|---|---|---|
| 类别 | byte, short, int, long, float, double, char, boolean |
所有类、接口、数组,包括 String |
| 存储位置 | 栈 | 栈(存储引用/地址),堆(存储对象数据) |
| 默认值 | 具体的零值 (如 0, false, '\u0000') | null |
| 行为 | 无方法,只有值 | 可以调用方法(如 str.length()) |
| 比较方式 | 比较值 | 比较地址是否相同;equals() 通常比较内容 |
String 特点 |
- | 不可变性、字面量语法、字符串常量池 |
请务必记住:String 是一个对象,是 Java 中最重要的引用类型之一,而不是基本类型。
