What 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.
Distinguishing between objects and objects for Java beginners, There is always doubt about string being an immutable Object. Look at the following code:
[java]View PlainCopy
- String s = "abcabc";
- System.out.println ("s =" + s);
- s = "123456";
- System.out.println ("s =" + s);
Print Result: s = abcabc
s = 123,456 First create a String object s, then let s the value of "abcabc", and then let the value of S is "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 is as follows: a different point in Java and C + + is that it is not possible to manipulate the object itself directly in java, all objects are pointed to by a reference and must be accessed by this reference to access the object itself, including the value of the member variable, the change of the Object's member variable, the method of invoking the object, etc. 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:
[java]View PlainCopy
- 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
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:
[java]View PlainCopy
- 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
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 real 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 these Values. therefore, 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:
[java]View PlainCopy
- String A = "abcabc";
- System.out.println ("a =" + a);
- A = A.replace (' A ', ' a ');
- System.out.println ("a =" + a);
The printed result is: a = Abcabc
A = Abcabc so 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 illustrates the problem: the reader can view the other methods themselves, recreating 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:
[java]View PlainCopy
- String ss = "123456";
- System.out.println ("ss =" + ss);
- Ss.replace (' 1 ', ' 0 ');
- 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:
[java]View PlainCopy
- Public static void Testreflection () throws Exception {
- //create string "Hello world" and assign to reference s
- String s = "Hello world";
- System.out.println ("s =" + s); //hello world
- //gets the Value field in the String class
- Field valuefieldofstring = String. Class.getdeclaredfield ("value");
- //change the access rights of the Value property
- Valuefieldofstring.setaccessible (true);
- //gets The value of the Value property on the S object
- 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, the so-called "immutable" object can be modified by Reflection. 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 not mutable
Java string immutable object, but StringBuffer is a mutable object