侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Java中String类的不可变性

2025-12-12 / 0 评论 / 4 阅读

题目

Java中String类的不可变性

信息

  • 类型:问答
  • 难度:⭐

考点

String不可变性,字符串池,字符串操作

快速回答

String对象在Java中是不可变的,主要特点包括:

  • 一旦创建,内容不可修改
  • 字符串拼接等操作会创建新对象
  • 使用字符串池(String Pool)优化内存
  • 线程安全,无需额外同步
## 解析

1. 不可变性原理

String类使用final char[] value存储字符数据,且不提供修改数组内容的方法。关键源码:

public final class String {
    private final char value[];
    // 无修改value数组的public方法
}

任何看似修改的操作(如concat()replace())都返回新创建的String对象,原对象不变。

2. 代码示例

String s1 = "hello";
String s2 = s1.concat(" world");  // 创建新对象

System.out.println(s1);  // 输出:hello(未改变)
System.out.println(s2);  // 输出:hello world

s1.toUpperCase();        // 返回新对象,但未接收
System.out.println(s1);  // 仍输出:hello

3. 字符串池(String Pool)机制

  • 使用字面量(如"abc")创建字符串时,JVM会检查字符串池是否存在相同内容
  • 若存在则直接返回池中引用,否则创建新对象并加入池中
  • new String("abc")会强制在堆中创建新对象(不推荐)
String a = "cat";         // 放入字符串池
String b = "cat";         // 复用池中对象
String c = new String("cat"); // 在堆中新建对象

System.out.println(a == b); // true(相同引用)
System.out.println(a == c); // false(不同对象)

4. 最佳实践

  • 字符串拼接:优先使用StringBuilder(非线程安全)或StringBuffer(线程安全)避免频繁创建对象
  • 比较相等:始终用equals()而非====比较引用地址)
  • 重用对象:尽量使用字面量声明字符串

5. 常见错误

  • 在循环中拼接字符串:
    // 错误示例:每次循环创建新String对象
    String result = "";
    for (int i = 0; i < 1000; i++) {
        result += i; // 性能极差!
    }
    
    // 正确做法:使用StringBuilder
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
        sb.append(i);
    }
    String result = sb.toString();
  • 误用==比较内容:
    String s1 = new String("java");
    String s2 = new String("java");
    System.out.println(s1 == s2); // false!应使用s1.equals(s2)

6. 扩展知识

  • 内存优化:不可性使字符串池成为可能,减少重复对象
  • 安全性:广泛用于网络连接、文件路径等场景,防止被篡改
  • HashCode缓存:String重写hashCode(),首次计算后缓存结果(因内容不变)