1. 简介
String 是 Java 中最核心的类之一,我们在之前的 String 相关系列教程 中已经对它做了大量介绍。
本文将重点讲解 Java 中 String 的初始化方式,包括声明与赋值的区别、字符串池机制、null 值处理等内容。
2. String 的创建方式
在 Java 中,创建 String 有两种常见方式:
- 使用
new
关键字 - 使用字符串字面量(literal)
String usingNew = new String("baeldung");
String usingLiteral = "baeldung";
✅ 推荐使用字面量方式,更简洁高效。
⚠️ 使用 new
会强制在堆中创建新对象,不推荐除非有特殊需求。
3. 仅声明 String 变量
我们可以在不赋值的情况下声明 String 变量:
public class StringInitialization {
String fieldString; // 成员变量自动初始化为 null
void printDeclaredOnlyString() {
String localVarString; // 局部变量未初始化
// System.out.println(localVarString); -> 编译错误
System.out.println(fieldString); // 输出 null
}
}
📌 要点总结:
- ✅ 成员变量自动初始化为
null
- ❌ 局部变量必须显式赋值后才能使用
- 如果局部变量赋值为
null
,它与未赋值的成员变量在值上是等价的
String localVarString = null;
assertEquals(fieldString, localVarString); // 成功通过
4. 使用字面量初始化 String
使用相同字面量创建多个 String 变量时,JVM 会利用字符串池优化:
String literalOne = "Baeldung";
String literalTwo = "Baeldung";
比较引用地址:
assertTrue(literalOne == literalTwo); // ✅ 成功通过
📌 原理说明:
- 字符串池中只会保存一份相同的字符串字面量
- 第一个赋值会将字符串放入池中,后续相同字面量会复用
5. 使用 new 初始化 String
使用 new
关键字创建 String 会绕过字符串池:
String newStringOne = new String("Baeldung");
String newStringTwo = new String("Baeldung");
虽然内容相同,但地址不同:
assertFalse(newStringOne == newStringTwo); // ✅ 成功通过
📌 要点总结:
new String("xxx")
总是创建新对象- 适合需要多个不同引用但内容相同字符串的场景(极少)
6. 空字符串初始化
创建空字符串有三种常见方式:
String emptyLiteral = ""; // 字面量,放入池中
String emptyNewString = new String(""); // new,不放入池中
String emptyNewStringTwo = new String(); // new,不放入池中
📌 比较结果:
assertFalse(emptyLiteral == emptyNewString); // 地址不同
assertFalse(emptyLiteral == emptyNewStringTwo); // 地址不同
assertFalse(emptyNewString == emptyNewStringTwo);// 地址不同
assertEquals(emptyLiteral, emptyNewString); // 内容相同
assertEquals(emptyNewString, emptyNewStringTwo); // 内容相同
✅ 所有空字符串内容一致,但引用不同(除非是字面量复用)
7. null 值处理
声明一个 null String:
String nullValue = null;
打印时输出的是 "null"
,但这只是 Java 的默认处理方式。
📌 为什么打印 null 会输出 "null"?
查看 PrintStream.println(Object)
源码:
public void println(Object x) {
String s = String.valueOf(x);
...
}
再看 String.valueOf(Object)
:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
✅ 所以,打印 null 实际上是调用 String.valueOf()
的结果,而不是 null 本身。
⚠️ 如果对 null 调用方法,会抛出 NullPointerException
,例如:
nullValue.length(); // 抛出 NullPointerException
8. 总结
本文详细讲解了 Java 中 String 的初始化方式,包括:
初始化方式 | 是否入池 | 是否创建新对象 | 默认值 | 推荐程度 |
---|---|---|---|---|
字面量 | ✅ 是 | ❌ 否 | 无 | ✅ 强烈推荐 |
new String("xxx") | ❌ 否 | ✅ 是 | 无 | ⚠️ 谨慎使用 |
null | - | - | null | ✅ 合理使用 |
空字符串字面量 | ✅ 是 | ❌ 否 | "" | ✅ 推荐 |
📌 最佳实践建议:
- ✅ 优先使用字面量初始化字符串
- ❌ 避免不必要的
new String("xxx")
- ✅ 理解 null 与空字符串的区别
- ✅ 理解字符串池机制,避免踩坑
所有示例代码均可在 GitHub 仓库 获取。