Java字符串的不可变

Java字符串的不可变

更新于 2025-04-28

openjdk 11openjdk17运行代码的结果会有不同。

出于安全策略,setAccessible(true)方法会抛出异常:

1java.lang.reflect.InaccessibleObjectException:
2Unable to make field private final byte[] java.lang.String.value accessible:
3module java.base does not "opens java.lang" to unnamed module @1a2a0702

 1/**
 2 * How to understand string immutable in java?<br>
 3 * 
 4 * 1. 线程安全性<br>
 5 * 2. 性能提升(缓存)<br>
 6 * 3. HashCode不变,避免散列表异常<br>
 7 * <br>
 8 * 
 9 * 所有对字符串的更改,都会创建一个新的字符串。<br>
10 * 
11 * 实际上是Java语言的约束,所以String类以及value域才用final修饰。<br>
12 * 
13 * 可以通过反射修改字符串。但是这样会有副作用。<br>
14 * 
15 * 如果要使用可变字符串,使用<code>StringBuffer</code>。
16 */
17
18class ImmutableStr {
19
20    /**
21     * @param args
22     */
23    public static void main(String[] args) {
24        String str = "spam";
25        System.out.printf("Before: literal: %s, hashCode: %s\n",
26                str,
27                str.hashCode());
28
29        Class<? extends String> clazz = str.getClass();
30        try {
31            Field f = clazz.getDeclaredField("value");
32            f.setAccessible(true);
33            byte[] strByte = (byte[]) f.get(str);
34            // Stream.of(strByte).forEach(System.out::print);
35            strByte[0] = 'S';
36        } catch (Exception e) {
37            e.printStackTrace();
38        }
39
40        System.out.printf("After: literal: %s, hashCode: %s\n",
41                str,
42                str.hashCode());
43
44        // 字面量已经更改了,但是hashCode没变
45        // 真的是同一个字符串么?
46        String otherString = "Spam";
47
48        System.out.println(
49                str.charAt(0) == otherString.charAt(0)); // true
50        System.out.println(str == otherString); // false
51        System.out.printf("hashCode of otherString: %s\n",
52                otherString.hashCode());
53
54    }
55}
56/*
57 * 程序运行警告
58 * WARNING: An illegal reflective access operation has occurred
59 * WARNING: Illegal reflective access by ImmutableStr
60 * (file:/__/redhat.java/jdt_ws/snippets_5eaf7742/bin/) to field
61 * java.lang.String.value
62 * WARNING: Please consider reporting this to the maintainers of ImmutableStr
63 * WARNING: Use --illegal-access=warn to enable warnings of further illegal
64 * reflective access operations
65 * WARNING: All illegal access operations will be denied in a future releas
66 */