理解 String 类的核心特性:不可变性、线程安全与接口实现
掌握 String 的常用构造方法及其适用场景
能区分字面量创建与 new 关键字创建字符串的内存差异
了解 String 在 Java 体系中的基础地位与设计哲学
String 对象一旦创建,其内容无法被修改。这是 Java 字符串设计的基石。
public class Main {
public static void main(String[] args) {
String text = "hello";
// text.charAt(0) = 'H'; // ❌ 编译错误!
}
}🔍 原因解析:
charAt(0)返回的是一个char值(右值),不是可赋值的变量(左值)所有“修改”操作(如
toUpperCase()、replace())都返回新对象,原对象不变
✅ 优势:
支持字符串常量池(节省内存)
天然线程安全
可作为 HashMap 的可靠键
由于不可变,多个线程可并发读取同一个 String 对象而无需加锁。
// 安全地在多线程中共享
public static final String CONFIG_PATH = "/app/config.json";
// 任何线程调用都不会导致数据不一致String 是 java.lang 包中的预定义 final 类,提供大量实用方法:
String str = "hello coder";
System.out.println("长度: " + str.length()); // 11
System.out.println("转大写: " + str.toUpperCase()); // HELLO CODER常用方法包括:
length()、charAt()、substring()、equals()、indexOf()、trim()等详见《Java 字符串常用方法详解》
String 类实现了三个重要接口,赋予其强大能力:
// 因为实现了 Comparable,可以直接排序
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Collections.sort(names); // 按字母顺序排序虽然通常使用字面量(如 String s = "Hello";),但 String 类提供了多种构造器以满足不同数据源的转换需求。
public class CoderHub {
public static void main(String[] args) {
// 1. 使用 new 关键字(不推荐常规使用)
String s1 = new String("Hello Java");
// 2. 从字符数组创建
char[] chars = {'J', 'A', 'V', 'A'};
String s2 = new String(chars);
// 3. 从字节数组创建(默认平台编码)
byte[] bytes = {72, 101, 108, 108, 111}; // ASCII: H e l l o
String s3 = new String(bytes);
System.out.println(s1); // Hello Java
System.out.println(s2); // JAVA
System.out.println(s3); // Hello
}
}⚠️ 注意:
new String("text")会在堆中创建新对象,即使常量池中已存在相同内容,通常应避免。
import java.nio.charset.StandardCharsets;
public class SafeStringCreation {
public static void main(String[] args) {
byte[] data = {(byte)0xE4, (byte)0xBD, (byte)0xA0, (byte)0xE5, (byte)0xA5, (byte)0xBD}; // "你好" 的 UTF-8 字节
// ✅ 显式指定 UTF-8,避免平台依赖导致乱码
String safe = new String(data, StandardCharsets.UTF_8);
System.out.println(safe); // 你好
// ❌ 危险:依赖默认编码(Windows 可能是 GBK,Linux 是 UTF-8)
// String unsafe = new String(data);
}
}不可变性是 String 设计的核心,带来安全性、线程安全与性能优化
线程安全源于状态不可变,无需同步机制
丰富方法覆盖文本处理绝大多数场景
多接口实现使其能融入 Java 集合、IO、序列化等体系
构造方法多样,适用于字节流、字符数组等底层数据转换
内存管理需理解常量池与堆的区别,避免不必要的 new
设计哲学:“简单性、安全性、一致性” ——
String的不可变设计体现了 Java 对可靠性优先于灵活性的工程取舍。
为什么 String 被设计为 final 类?如果允许继承,可能带来哪些安全风险?
在网络编程中接收字节流时,为什么必须显式指定字符集(如 UTF-8)来构造 String?请举例说明默认编码可能导致的问题。
给定以下代码,共创建了多少个 String 对象?分别位于内存哪个区域?
String s1 = "Code";
String s2 = new String("Code");
String s3 = s2.intern();
String s4 = "Code";