1. Introduction to immutable categories
Immutable class: The so-called immutable class means that once an instance of this class is created, its member variable value cannot be changed. For example, many immutable classes that come with JDK: Interger, Long and String, etc.
Variable classes: Compared with immutable classes, mutable classes can change their member variable values after creating instances. Most classes created in development belong to mutable classes.
2. Advantages of immutable classes
After talking about the difference between mutable classes and immutable classes, we need to further understand why there are immutable classes? What benefits does such a feature bring to JAVA?
1. Thread safety
Immutable objects are thread-safe and can be shared between threads. There is no need to use special mechanisms to ensure synchronization problems, because the value of the object cannot be changed. It can reduce the possibility of concurrent errors, because there is no need to use some lock mechanisms to ensure memory consistency problems, which also reduces synchronization overhead.
2. Easy to construct, use and test
3....
Immutable class design method
For design immutable classes, I personally summarize the following principles:
1. Add a final modifier to the class to ensure that the class is not inherited.
If a class can be inherited, it will destroy the class's immutability mechanism, as long as the inheritance class overrides the parent class's methods and the inheritance class can change the member variable value, then once the child class appears as the parent class, it cannot be guaranteed whether the current class is mutable.
2. Ensure that all member variables must be private and final modification is added
This way ensures that member variables are unchangeable. But it is not enough to do this, because if it is an object member variable, it is possible to change its value externally. So the fourth point makes up for this shortcoming.
3. No methods are provided to change member variables, including setters
Avoid changing the value of member variables through other interfaces and destroying immutable features.
4. Initialize all members through the constructor and perform deep copy (deep copy)
If the object passed in by the constructor is directly assigned to the member variable, it can still be changed by modifying the incoming object, which will cause the value of the internal variable to be changed. For example:
public final class ImmutableDemo { private final int[] myArray; public ImmutableDemo(int[] array) { this.myArray = array; // wrong } }This method cannot guarantee immutability. MyArray and array point to the same memory address. Users can change the value inside myArray by modifying the value of the array object outside of ImmutableDemo.
In order to ensure that the internal value is not modified, depth copy can be used to create a new memory to save the incoming value. Correct way to do it:
public final class MyImmutableDemo { private final int[] myArray; public MyImmutableDemo(int[] array) { this.myArray = array.clone(); } }5. In the getter method, do not return the object itself directly, but clone the object and return the copy of the object.
This approach also prevents object leakage and prevents direct operation of member variables after obtaining internal mutable member objects through getters, resulting in changes in member variables.
IV. Immutability of String objects
The string object cannot be changed after memory creation. The creation of immutable objects generally meets the above 5 principles. Let's take a look at how the String code is implemented.
public final class Stringimplements 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..public String(char value[]) {this.value = Arrays.copyOf(value, value.length); // deep copy operation}...public char[] toCharArray() {// Cannot use Arrays.copyOf because of class initialization order issueschar result[] = new char[value.length];System.arraycopy(value, 0, result, 0, value.length);return result;}...}As shown in the above code, the following design details can be observed:
1.String class is modified by final and cannot be inherited
2. All members of string are set as private variables
3. The value setter does not exist
4. And set value and offset to final.
5. When passing in a variable array value[], copy it instead of copying the value[] directly to the internal variable.
6. When obtaining the value, it does not directly return the object reference, but returns the object's copy.
This is consistent with the characteristics of the invariant type summarized above, and also ensures that the String type is an immutable class.
5. Advantages and disadvantages of immutability of String objects
From the previous section analysis, String data is immutable, so what are the benefits of setting such a feature? I summarized it as follows:
1. Requirements for string constant pools.
String constant pools can reuse some character constants in the constant pool, avoiding recreating the same object every time and saving storage space. But if the string is variable, the String of the same content also points to the same memory space of the constant pool. When a variable changes the value of that memory, the other traversed values will also change. Therefore, it does not conform to the original intention of constant pool design.
2. Thread safety considerations.
The same string instance can be shared by multiple threads. This way, there is no need to use synchronization due to thread safety issues. Strings are thread-safe.
3. Class loaders need to use strings, and immutability provides security so that the correct class is loaded. For example, if you want to load the java.sql.Connection class and this value is changed to myhacked.Connection, it will cause unknown damage to your database.
4. Support hash mapping and caching.
Because strings are immutable, the hashcode is cached when it is created and does not need to be recalculated. This makes strings very suitable as keys in Map, and the processing speed of strings is faster than other key objects. This is why keys in HashMap often use strings.
shortcoming:
1. If there is a need to change the value of the String object, a large number of String objects will be created.
6. Is the String object really immutable?
Although the String object sets the value to final, it also ensures that its member variables are unchangeable through various mechanisms. However, it can still be changed through the reflection mechanism. For example:
//Create the string "Hello World" and assign it to the reference sString s = "Hello World"; System.out.println("s = " + s); //Hello World//Get the value field in the String class Field valueFieldOfString = String.class.getDeclaredField("value");//Change the access permission of the value attribute valueFieldOfString.setAccessible(true);//Get the value attribute value on the s object char[] value = (char[]) valueFieldOfString.get(s);//Change the 5th character value[5] in the array referenced by the value = '_';System.out.println("s = " + s); //Hello_WorldThe print result is:
s = Hello Worlds = Hello_World
It was found that the value of String has changed. That is to say, the so-called "immutable" object can be modified through reflection.
Summarize
An immutable class is the value of the member traversal that cannot be changed after the instance is created. This feature allows immutable classes to provide thread-safe features but also brings overhead of object creation. Each change of attribute is to recreate a new object. JDK also provides many immutable classes such as Integer, Double, String, etc. The immutable characteristics of String are mainly to meet the needs of constant pooling, thread safety, and class loading. Rational use of immutable classes can bring great benefits.
The above is the immutable mechanism of the JAVA (immutable) and the immutability of String (recommended) introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!