turn from: http://www.2cto.com/kf/201401/272974.html, thank you for the summary of the authorWhat is an immutable object?
As we all know, in Java, the string class is immutable. So what exactly is an immutable object? It can be said that if an object cannot change its state after it has been created, then the object is immutable. The inability to change the state means that the member variables within the object cannot be changed, that the value of the underlying data type cannot be changed, that a variable of the reference type cannot point to other objects, and that the state of the object to which the reference type points cannot be changed.
Differentiating objects and objects from references
For Java beginners, there is always doubt that a string is an immutable object. Look at the following code:
1 String s = "ABCABC" Span style= "color: #000000;" >; 2 System.out.println ("s =" + s); 3 s = "123456" ; 4 System.out.println ("s =" + s);
Print Result: s = abcabc
s = 123456
First create a String object s, then the value of S to "ABCABC", and then let s the value "123456". As you can see from the printout, the value of S has indeed changed. So how do you say the string object is immutable? In fact, there is a misunderstanding: s is just a reference to a string object, not the object itself. An object is an area of memory in memory, and the more member variables, the greater the amount of space that the memory area occupies. A reference is just a 4-byte data that contains the address of the object it points to, and the object can be accessed by this address. That is, S is just a reference, it points to a specific object when s= "123456"; After this code was executed, a new object "123456" was created, and the reference S re-pointed to the object of the heart, the original object "Abcabc" still exists in memory, and has not changed. The memory structure looks like this:
A different point of Java and C + + is that in Java it is not possible to manipulate the object itself directly, all objects are pointed to by a reference, which must be used to access the object itself, including getting the value of the member variable, changing the object's member variables, invoking the object's methods, and so on. In C + + There are references, objects and pointers to three things, and these three things can access the object. In fact, the references in Java are conceptually similar to the pointers in C + +, they are the address values of the stored object in memory, but in Java, the reference loses some flexibility, such as a reference in Java cannot be added and reduced as a pointer in C + +.
Why is the string object immutable?
To understand the immutability of a string, first look at what member variables are in the string class. In JDK1.6, there are several member variables for string:
1 Public Final classString2 ImplementsJava.io.Serializable, comparable<string>, Charsequence3 {4 /**The value is used for character storage.*/5 Private Final Charvalue[];6 7 /**The offset is the first index of the storage, which is used.*/8 Private Final intoffset;9 Ten /**The count is the number of characters in the String.*/ One Private Final intcount; A - /**Cache The hash code for the string*/ - Private intHash//Default to 0</string>
In JDK1.7, the string class made some changes, mainly changing the behavior of the substring method when it was executed, which is irrelevant to the topic in this article. The main member variables of the string class in JDK1.7 are two:
1 Public Final classString2 ImplementsJava.io.Serializable, comparable<string>, charsequence {3 /**The value is used for character storage.*/4 Private Final Charvalue[];5 6 /**Cache The hash code for the string*/7 Private intHash//Default to 0</string>
As can be seen from the above code, in Java the String class is actually the encapsulation of the character array. In JDK6, value is an array of string wrappers, offset is the starting position of string in this value array, and count is the number of characters that the string occupies. In JDK7, there is only one value variable, that is, all characters in value are of the object of string. This change does not affect the discussion in this article. In addition to this, there is a hash member variable, which is the cache of the hash value of the string object, and this member variable is not related to the discussion in this article. In Java, an array is also an object (you can refer to my previous article in Java for an array of attributes). So value is just a reference, it points to a real array object. Actually executed a string s = "ABCABC"; After this code, the actual memory layout should look like this:
The three variables of Value,offset and count are private, and no public methods such as SetValue, SetOffset, and SetCount are available to modify the values, so the string cannot be modified outside the string class. This means that once the initialization is not modified, and the three members cannot be accessed outside the string class. In addition, the three variables of Value,offset and count are final, that is, within the string class, once the three values are initialized, they cannot be changed. So you can think of a string object as immutable.
So in string, there are some methods that can be called to get the changed values. These methods include substring, replace, ReplaceAll, toLowerCase and so on. For example, the following code:
1 String a = "Abcabc"; 2 System.out.println ("a =" + a); 3 a = A.replace (' A ', ' a '); 4 System.out.println ("a =" + a);
The printed result is: a = Abcabc
A = Abcabc
Then the value of a seems to change, in fact, it is the same misunderstanding. Again, A is just a reference, not a real string object, when calling A.replace (' a ', ' a '), a new string object is created inside the method, and the object of the heart is re-assigned to reference a. The source code of the Replace method in string can explain the problem:
The reader can view the other methods by re-creating the new string object inside the method, and returning the new object, the original object will not be changed. This is why there are return values for methods such as replace, Substring,tolowercase, and so on. It is also why the call does not change the value of the object as follows:
1 String ss = "123456"; 2 System.out.println ("ss =" + ss); 3 ss.replace (' 1 ', ' 0 '); 4 System.out.println ("ss =" + ss);
Print Result: ss = 123456
SS = 123456
Is the string object really immutable?
From the above, it is known that the member variable of the string is private final, which is not changed after initialization. So in these few members, value is more special because he is a reference variable, not a real object. Value is final decorated, that is, final cannot point to other array objects, can I change the array that value points to? For example, change a character in an array to an underscore "_". At least not in the ordinary code we write ourselves, because we simply cannot access this value reference, nor can we modify the array by this reference. So what is the way to access a private member? Yes, with reflection, you can reflect the Value property in a String object and change the structure of the array by the value reference obtained. Here is the instance code:
1 Public Static voidTestreflection ()throwsException {2 3 //Create the string "Hello world" and assign it to the reference s4String s = "Hello World"; 5 6System.out.println ("s =" + s);//Hello World7 8 //Get the Value field in the String class9Field valuefieldofstring = String.class. Getdeclaredfield ("value");Ten One //changing the access rights of the Value property AValuefieldofstring.setaccessible (true); - - //gets the value of the Value property on the S object the Char[] Value = (Char[]) valuefieldofstring.get (s); - - //Change the 5th character in the array referenced by value -Value[5] = ' _ '; + -System.out.println ("s =" + s);//Hello_world +}
Print Result: s = Hello World
s = Hello_world
In this process, s always refers to the same string object, but before and after the reflection, the string object has changed, that is to say, by reflection, the so-called immutable object can be modified. But generally we do not do so. This example of reflection can also illustrate a problem: If an object, the state of his group of other objects can be changed, then this object is probably not immutable object. For example, a car object, which combines a wheel object, although the wheel object is declared as private final, but the internal state of the wheel object can be changed, it is not very good to ensure that the car object is immutable.
The Java learning string object is what is immutable