Reprinted: https: //www.cnblogs.com/leskang/p/6110631.html
First, what is an immutable object?
As we all know, in Java in, String class object is immutable. So in the end what is immutable objects? Can be considered: If an object after it is created, can not change its state, then the object is immutable. Means that the state can not be changed, can not be changed in the member variable objects, including basic data type value can not be changed, the variable reference type can not point to other objects (final modification), the type state of an object reference pointing to not change.
Second, the distinction between objects and object references
For Java beginner, for String objects are immutable there is always a doubt. Look at the code below:
String s = "ABCabc"; System.out.println("s = " + s); s = "123456"; System.out.println("s = " + s);
Print results: s = ABCabc
first create a String object s, and then let the value of s is "ABCabc", and then letting s is "123456." As can be seen from the printed results, it does change the value of s. So how String objects are immutable said it? In fact, there is a misunderstanding here: s just a String object reference, not the object itself . The object is a memory area in the memory, the more the member variables, the greater this memory area occupied space. References only a 4-byte data, stored inside the object it points to the address of the object can be accessed via this address. That, s just a reference that points to a specific object, when s = "123456"; After this code executed, and create a new object "123456" and a reference point to the re s heart object, the original object "ABCabc" still heap in existence, it has not changed. Memory structure as shown below:
tips: One difference between Java and C ++ is that direct manipulation object itself is impossible in Java, all objects referenced by a point, must pass this reference to access the object itself, including the value of the acquisition member variables change member objects variable, call the object's methods. And there is a reference in C ++, objects and pointers three things, three things can access the object. In fact, the pointer reference in Java and C ++ are conceptually similar, the object of their address values are stored in memory, but in Java, citing lost some flexibility, such as references in Java can not be like addition and subtraction is performed as in C ++ pointer .
Third, why String objects are immutable?
To understand the immutability of String, first look at what are the String class member variables. In JDK1.6, String member variables are the following:public final class String
implements java.io.Serializable, Comparable<string>, CharSequence{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0</string>
public final class String implements java.io.Serializable, Comparable<string>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0</string>
value, offset and count these three variables are private, and does not provide setValue, setOffset and setCount other public methods to modify these values can not be edited in an external String String class. That can not be changed once initialized, and can not be accessed outside of the three members of the String class. In addition, value, offset and count these three variables are final, that is inside the String class, once these three values initialized and can not be changed. It can be considered String objects are immutable up.
So in a String, obviously there are some methods, call the changed value they can get. These methods include substring, replace, replaceAll, toLowerCase like. For example the following code:
String a = "ABCabc"; System.out.println("a = " + a); a = a.replace('A', 'a'); System.out.println("a = " + a);
Print results: a = ABCabc
then the value of a seemingly changed, it is still the same errors. Again, a reference to a just, is not a true string object, when calling a.replace ( 'A', 'a '), the internal method creates a new String object , and this new object is re-assigned a reference to a. String replace method in the source code can describe the problem
String ss = "123456"; System.out.println("ss = " + ss); ss.replace('1', '0'); System.out.println("ss = " + ss);
打印结果: ss = 123456
四、String对象真的不可变吗?
从上文可知String的成员变量value是private final 的,也就是初始化之后不可改变。那么在这几个成员中, value比较特殊,因为他是一个引用变量,而不是真正的对象。value是final修饰的,也就是说final不能再指向其他数组对象,那么我能改变value指向的数组吗? 比如将数组中的某个位置上的字符变为下划线“_”。 至少在我们自己写的普通代码中不能够做到,因为我们根本不能够访问到这个value引用(private修饰),更不能通过这个引用去修改数组。 那么用什么方式可以访问私有成员呢? 没错,用反射, 可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。下面是实例代码:
public static void testReflection() throws Exception {
//创建字符串"Hello World", 并赋给引用s
String s = "Hello World";
System.out.println("s = " + s); //Hello World
//获取String类中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
//改变value属性的访问权限
valueFieldOfString.setAccessible(true);
//获取s对象上的value属性的值
char[] value = (char[]) valueFieldOfString.get(s);
//改变value所引用的数组中的第5个字符
value[5] = '_';
System.out.println("s = " + s); //Hello_World
}
打印结果为: s = Hello World
with a String object in this process, s always cited, but then reflected back and forth, the String object has changed, that is, by reflection can be modified so-called "immutable" object. But generally we do not do. This reflected instance can also indicate a problem: If an object, other objects of his state combination can not change, but the object is probably not immutable. For example, a Car object, which combines a Wheel object Wheel although this statement has become the object of private final, but the state of the Wheel inside the object can be changed, then we can not guarantee a good Car immutable objects.