Home>

I. Introduction to Immutable Classes

Immutable class:The so-called immutable class means that once an instance of this class is created,You cannot change the value of its member variables.Such as jdk comes with many immutable classes:interger, long and string.

Mutable classes:Relative to immutable classes,A mutable class can change the value of its member variables after creating an instance.Most classes created in development are mutable.

Second, the advantages of immutable classes

After talking about the difference between mutable and immutable classes,We need to learn more about why there are immutable classes?What benefits does this feature bring to Java?

Thread safety

Immutable objects are thread-safe,Can be shared among threads,No special mechanism is needed to guarantee synchronization issues,Because the value of the object cannot be changed.Can reduce the possibility of concurrent errors,Because there is no need to use some locking mechanism to ensure memory consistency, it also reduces synchronization overhead.

2. Easy to construct, use and test

3 ....

Design methods for immutable classes

For designing 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 break the immutability of the class,As long as the inheriting class overrides the method of the parent class and the inheriting class can change the value of the member variable,Then once the child class appears as the parent class,There is no guarantee that the current class is mutable.

2. Ensure that all member variables must be private,And finally

In this way, member variables are guaranteed to be immutable.But this step is not enough,Because if it is an object member variable, its value may be changed externally.So point 4 makes up for this deficiency.

3. Does not provide methods to change member variables,Including setter

Avoid changing the value of member variables through other interfaces,Destroy immutable properties.

4. Initialize all members through the constructor,Make a deep copy

If the object passed by the constructor is directly assigned to a member variable,It is still possible to change the value of the internal variable by modifying the incoming object.E.g:

public final class immutabledemo {
private final int [] myarray;
public immutabledemo (int [] array) {
this.myarray=array;//wrong
}
}

This method does not guarantee immutability,myarray and array point to the same memory address,Users can change the value of myarray outside the immutabledemo by modifying the value of the array object.

To ensure that internal values ​​are not modified,You can use deep copy to create a new memory to hold the incoming value.Correct way:

public final class myimmutabledemo {
private final int [] myarray;
public myimmutabledemo (int [] array) {
this.myarray=array.clone ();
}
}

5. In the getter method, do not directly return the object itself,But clone objects,And return a copy of the object

This practice also prevents the leakage of objects,Prevent direct manipulation of member variables after getting internal variable member objects through getters,Causes member variables to change.

Fourth, the immutability of the string object

The string object cannot be changed after it is created in memory.The creation of immutable objects generally meets the above five principles. Let's see how the string code is implemented.

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
....
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 issues
char result []=new char [value.length];
system.arraycopy (value, 0, result, 0, value.length);
return result;
}
...
}

As shown in the code above,The following design details can be observed:

1. The string class is final and cannot be inherited

2.All members of the string are set to private variables

3. There is no setter for value

4. Set value and offset to final.

5. When a variable array value [] is passed in, copy is performed instead of directly copying value [] to the internal variable.

6. Instead of directly returning an object reference when getting value,Instead, it returns a copy of the object.

This is consistent with the characteristics of the invariant types summarized above,It also guarantees that the string type is an immutable class.

Five, the advantages and disadvantages of the immutability of the string object

Analyzing from the previous section,string data immutable class,So what's the benefit of setting such a feature?I summarize it as follows:

1. The need for a string constant pool.

The string constant pool can reuse some character constants in the constant pool.Avoid recreating the same objects every time, saving storage space.But if the string is mutable,At this time, the same content string also points to the same memory space of the constant pool.When a variable changes the value of this memory,Other traversed values ​​will also change.So it does not meet the original intention of the constant pool design.

2. Thread safety considerations.

The same string instance can be shared by multiple threads.This eliminates the need to use synchronization for thread safety issues.Strings are themselves thread-safe.

3. The class loader uses strings,Immutability provides security,So that the correct classes are loaded.For example, if i want to load the java.sql.connection class, and this value is changed to myhacked.connection, then it will cause unknown damage to your database.

4. Support hash mapping and caching.

Because strings are immutable,So the hashcode is cached when it is created,No need to recalculate.This makes strings very suitable as keys in maps. Strings are processed faster than other key objects.This is why keys in hashmaps often use strings.

Disadvantages:

1. If there is a need to change the value of the string object,Then a lot of string objects will be created.

Six, is the string object really immutable?

Although the string object sets the value to final, and its member variables are immutable through various mechanisms.But its value can still be changed by means of reflection mechanism.E.g:

//Create the string "hello world" and assign it to the reference s
string 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 rights of the value attribute
valuefieldofstring.setaccessible (true);
//Get the value of the value property on the s object
char [] value=(char []) valuefieldofstring.get (s);
//Change the fifth character in the array referenced by value
value [5]="_";
system.out.println ("s =" + s);//hello_world

The print result is:

s=hello world
s=hello_world

Found that the value of string has changed.That is,It is possible to modify so-called "immutable" objects through reflection

to sum up

Immutable classes are members whose values ​​cannot be traversed after the instance is created.This feature makes immutable classes provide thread-safe features but also brings the overhead of object creation.Every time you change a property, you recreate a new object.jdk also provides many immutable classes such as integer, double, string, etc. The immutability of string is mainly to meet the needs of constant pool, thread safety, and class loading.Proper use of immutable classes can bring great benefits.

  • Previous Comprehensive analysis of the differences between $Apply () and $Digest () in Angular
  • Next JavaScript learning summary of the abandoned eval function and with statement examples