Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Why String in Java is immutable

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "why the String in Java is immutable". In the daily operation, I believe that many people have doubts about why the String in Java is immutable. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the question of "Why is the String in Java immutable?" Next, please follow the editor to study!

What is an immutable object?

As we all know, in Java, the String class is immutable. So what exactly is an immutable object? You can think of it this way: if an object cannot change its state after it has been created, then the object is immutable. Unable to change the state means that the member variables within the object, including the values of the basic data types, cannot be changed, the variables of the reference type cannot point to other objects, and the state of the object pointed to by the reference type cannot be changed.

Distinguish between objects and references to objects

For Java beginners, there is always doubt that String is an immutable object. Look at the following code:

String s = "ABCabc"

System.out.println ("s =" + s)

S = "123456"

System.out.println ("s =" + s)

The print result is as follows:

S = ABCabc

S = 123456

First create a String object s, then make the value of s "ABCabc", and then let the value of s be "123456". As can be seen from the print results, the value of s has indeed changed. So why do you say that String objects are immutable? In fact, there is a misunderstanding: s is just a reference to a String object, not the object itself. The object is a memory area in memory, and the more member variables, the more space this memory area takes up. A reference is just a 4-byte data that contains the address of the object it points to, through which the object can be accessed.

In other words, s is just a reference that points to a specific object when s = "123456"; after this code is executed, a new object "123456" is created, while the reference s repoints to the heart object, and the original object "ABCabc" still exists in memory and remains unchanged. The memory structure is shown in the following figure:

One difference between Java and C++ is that it is impossible to directly manipulate the object itself in Java. All objects are pointed to by a reference, which is necessary to access the object itself, including obtaining the value of member variables, changing object member variables, calling object methods, and so on. In C++, there are three things: reference, object and pointer, all of which can access objects. In fact, references in Java are similar in concept to pointers in C++. They are both address values of stored objects in memory, but in Java, references lose some flexibility. For example, references in Java cannot add or subtract like pointers in C++.

Why are String objects immutable?

To understand the immutability of String, first take a look at what member variables are in the String class. In JDK1.6, String has the following member variables:

Public final class String implements java.io.Serializable, Comparable, 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 has made some changes, mainly changing the behavior of the substring method when it is executed, which is not relevant to the topic of this article. There are only two main member variables of the String class in JDK1.7:

Public final class String implements java.io.Serializable, Comparable, 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 you can see from the above code, the String class in Java is actually an encapsulation of an array of characters. In JDK6, value is an array encapsulated by String, offset is the starting position of String in this value array, and count is the number of characters occupied by String. In JDK7, there is only one value variable, that is, all the characters in value belong to the object String. This change does not affect the discussion of this article. In addition, 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, arrays are also objects (you can refer to the properties of arrays in my previous article, java). So value is also just a reference that points to a real array object. In fact, String s = "ABCabc" is executed; after this code, the real memory layout should look like this:

The three variables value,offset and count are private, and no public methods such as setValue, setOffset, and setCount are provided to modify these values, so String cannot be modified outside the String class. That is, once initialized, it cannot be modified, and the three members cannot be accessed outside the String class. In addition, the three variables value,offset and count are final, that is, in the inner part of the String class, once these three values are initialized, they cannot be changed. So the String object can be considered immutable.

So in String, there are obviously some methods that can be called to get the changed value. These methods include substring, replace, replaceAll, toLowerCase and so on. For example, the following code:

String a = "ABCabc"; System.out.println ("a =" + a); a = a.replace ('A','a'); System.out.println ("a =" + a)

The print result is as follows:

A = ABCabc

A = aBCabc

Then the value of a seems to have changed, but in fact it is the same misunderstanding. Again, an is just a reference, not a real string object. When you call a.replace ('A','a'), a new String object is created inside the method and the heart's object is reassigned to reference a. The source code of the replace method in String can illustrate the problem:

Readers can look at other methods themselves, all recreate a new String object inside the method, and return the new object, the original object will not be changed. This is why methods such as replace and substring,toLowerCase have return values. That's why a call like this does not change the value of the object:

String ss = "123456"; System.out.println ("ss =" + ss); ss.replace ('1percent,' 0'); System.out.println ("ss =" + ss)

Print the results:

Ss = 123456

Ss = 123456

Are String objects really immutable?

From the above, we can see that the member variable of String is private final, that is, it cannot be changed after initialization. So among these members, value is special because it is a reference variable, not a real object. Value is modified by final, which means that final can no longer point to other array objects, so can I change the array that value points to? For example, change the character at a certain position in the array to an underscore "_". At least not in the normal code we write, because we don't have access to the value reference at all, let alone modify the array through it.

So how can private members be accessed? Yes, with reflection, you can reflect the value property in the String object, which in turn changes the structure of the array through the obtained value reference. The following is the example code:

Public static void testReflection () throws Exception {/ / creates the string "Hello World" and assigns it to the reference s String s = "Hello World"; System.out.println ("s =" + s); / / Hello World / / gets the value field Field valueFieldOfString = String.class.getDeclaredField ("value") in the String class; / / changes the access to the value property valueFieldOfString.setAccessible (true) / / get the value of the value attribute on the s object char [] value = (char []) valueFieldOfString.get (s); / / change the fifth character value [5] ='_'in the array referenced by value; System.out.println ("s =" + s); / / Hello_World}

The print result is as follows:

S = Hello World

S = Hello_World

In this process, s always references the same String object, but the String object changes before and after rereflection, that is, the so-called "immutable" object can be modified by reflection. But we don't usually do that. This reflection example also illustrates a problem: if an object, the state of other objects it combines can be changed, then the object is probably not an 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, so it is not a good guarantee that the Car object is immutable.

At this point, the study of "Why the String in Java is immutable" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report