Java中的可变字符串 [英] Mutable strings in Java

查看:204
本文介绍了Java中的可变字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几乎每个人都知道Java中的字符串是不可变的。最近我发现了一些可能暗示它并不总是正确的东西。让我们试试这段代码:

As almost everybody knows strings in Java are immutable. Recently I discovered something that might suggest that it's not always true. Let's try out this code:

System.out.println("-------- BEFORE MODIFICATIONS --------");
String beforeTest = new String("Original");
System.out.println(beforeTest);
java.lang.reflect.Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set("Original", "Modified".toCharArray());
System.out.println("-------- AFTER MODIFICATIONS --------");
System.out.println(beforeTest);
System.out.println("Original");
String test = new String("Original");
System.out.println(test);
String test2 = new String("Original 2");
System.out.println(test2);

输出为:

-------- BEFORE MODIFICATIONS --------
Original
-------- AFTER MODIFICATIONS --------
Original
Modified
Modified
Original 2

这个技巧如何运作? JVM如何知道应该更改哪些对象以及哪些对象不应该更改?这个伎俩的机制是什么?为什么已经创建 beforeTest 字符串未更改?这个技巧真的会减损字符串是不可变的原则吗?

How does this trick work? How does the JVM know which objects should be changed and which not? What mechanism are under the hood of this trick? Why already created beforeTest string was not changed? Does this trick really derogate the strings are immutable principle?

推荐答案

字符串文字被插入池中。这意味着当你写

String literals are interned into a pool. This means that when you write

String s1 = "Foo";
String s2 = "Foo";
String s3 = new String("Foo");

s1和s2引用相同的String对象,s3引用另一个,由另一个char支持数组。

s1 and s2 refer to the same String object, and s3 refers to another one, backed by another char array.

在您的代码中,您通过修改包含原始字符串文字实例字符的私有字符数组来违反字符串的不变量。但是因为 beforeTest 引用了另一个String实例,所以它没有被修改。

In your code, you violate String's invariants by modifying the private char array holding the characters of the "Original" String literal instance. But since beforeTest refers to another String instance, it's not modified.

通过将字段保持为私有来实现不变性对象,并没有提供任何方法来修改这个私有状态。通过使用反射,您可以破坏所有封装规则,从而可以违反不变性。

Immutability is achieved by keeping fields private into an object, and not providing any method to modify this private state. By using reflection, you break all the rules of encapsulation, and you can thus violate immutability.

这篇关于Java中的可变字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆