Immutability of String

In the JDK, the class declaration about String is like this:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
}
Copy the code

As you can see, the String class is final, so String is an immutable object.

Immutable objects are objects whose internal state remains unchanged after they are fully created. This means that once an object is assigned to a variable, we can neither update the reference nor change the internal state in any way.

The value of a String is immutable. The value of a String is immutable. The value of a String is immutable.

String s = "abcd";
s = s.concat("ef");
Copy the code

So, doesn’t the operation change the string from “abcd” to “abcdef”?

However, even though the string content appears to have changed from “abcd” to “abcdef”, what we actually have is a new string.

As shown above, an “abcdef” string is recreated in the heap, not the same object as “abcd”.

Therefore, once a string is created in memory (the heap), it cannot be modified. Furthermore, all of the String methods do not change the value of the String itself, but return a new object.

If we want a modifiable String, we can use Either StringBuffer or StringBuilder instead of String.

Why is String designed to be immutable

After knowing that “strings are immutable”, you must be wondering: why make strings immutable? What are the benefits?

This question has puzzled many people, even James Gosling, the founder of Java, directly.

In an interview James Gosling was asked when immutable variables should be used, and his answer was:

I would use an immutable whenever I can.

So what’s the reason behind his answer? Based on what kind of thinking?

In fact, it is mainly from the perspective of cache, security, thread safety and performance.

The cache

Strings are the most widely used data structure. Creating large numbers of strings is very expensive, so Java provides string caching, which can save a lot of heap space.

There is a special space in the JVM for storing Java strings, called the string pool.

With string pooling, two string variables with the same content can point to the same string object from the pool, saving critical memory resources.

String s = "abcd";
String s2 = s;
Copy the code

For this example, s and s2 both stand for “abcd”, so they point to the same string object in the string pool:

However, this can be done mainly because of the immutability of strings. Imagine that if the string is mutable, if we change the contents of S, then the contents of S2 must be changed passively, which is obviously not what we want to see.

security

Strings are widely used in Java applications to store sensitive information, such as user names, passwords, connection urls, and network connections. JVM classloaders also use it extensively when loading classes.

Therefore, securing the String class is critical to improving the security of the entire application.

When we pass a string in a program, if the contents of the string are immutable, we can trust the contents of the string.

However, if it is mutable, the contents of the string can be modified at any time. Then the contents of the string are completely trusted. There’s no security in the whole system.

Thread safety

Immutable automatically makes strings thread-safe because they cannot be changed when accessed from multiple threads.

Therefore, immutable objects can generally be shared between multiple threads running at the same time. They are also thread-safe, because if the thread changes the value, a new string is created in the string pool instead of modifying the same value. Therefore, strings are safe for multithreading.

Hashcode cache

Since string objects are widely used as data structures, they are also widely used in hash implementations such as HashMap, HashTable, HashSet, and so on. The hashCode() method is often called when operating on these hash implementations.

Immutability guarantees that the value of a string will not change. Therefore, the hashCode() method is overridden in the String class to facilitate caching, so that the hash is computed and cached during the first hashCode() call and returns the same value from then on.

In the String class, there is the following code:

private int hash; //this is used to cache hash code.Copy the code

performance

String pooling, Hashcode caching, and so on, mentioned earlier, are all withdrawals that improve performance.

Because strings are immutable, you can use string pool caching, which can greatly save heap memory. Hashcode can also be cached ahead of time, which is more efficient

Because strings are the most widely used data structure, improving the performance of strings has a considerable impact on improving the overall performance of the entire application.

conclusion

From this article, we can conclude that strings are immutable, so their references can be treated as ordinary variables that can be passed between methods and threads without worrying about whether the actual string object it points to changes.

We also learned about other reasons that prompted Java language designers to make this class immutable. The main considerations are caching, security, thread safety and performance