Home  >  Article  >  Java  >  Is the String object in java mutable?

Is the String object in java mutable?

伊谢尔伦
伊谢尔伦Original
2016-12-05 10:54:111697browse

A friend posted a question on StackOverflow and asked:

It is known that the String object in Java is immutable, but let’s take a look at the following code:

String s1 = "Hello World";  
String s2 = "Hello World";  
String s3 = s1.substring(6);  
System.out.println(s1); // Hello World  
System.out.println(s2); // Hello World  
System.out.println(s3); // World  

Field field = String.class.getDeclaredField("value");  
field.setAccessible(true);  
char[] value = (char[])field.get(s1);  
value[6] = 'J';  
value[7] = 'a';  
value[8] = 'v';  
value[9] = 'a';  
value[10] = '!';  

System.out.println(s1); // Hello Java!  
System.out.println(s2); // Hello Java!  
System.out.println(s3); // World

Why is this code like this? operation result? Why are the values ​​of s1 and s2 changed, but the value of s3 is not?

Answer #1:

String objects are immutable, but that just means that you cannot change its value by calling its public methods.

The above code bypasses the normal API through reflection mechanism. In this way, you can also change the value of the enumeration, and even change the lookup table used when the Integer type is autoboxed.

Here, since s1 and s2 point to the same internal string object, their values ​​are both changed. As mentioned in other answers, this is implemented by the compiler.

The reason why s3 has not been changed really surprises me. I used to think that s3 and s1 share the same value array (this was indeed the case in versions before Java 7u6). However, by looking at the source code of the String class, we can see that the value array of the substring object is copied from the original string object (by using the Arrays.copyOfRange(..) method). This is the reason why s3 has not been changed.

You can install a SecurityManager to prevent malicious code from performing this type of operation. But it should be noted that the implementation of some libraries relies on this reflection technique (such as ORM tools, AOP libraries, etc.).

I wrote at the beginning of my reply that String objects are not really immutable, they just "look immutable". This may mislead readers into thinking that the current version of the String class is negligent in terms of access restrictions, but in fact the value array uses private and final modifiers. Therefore, developers need to pay attention: arrays cannot be declared immutable in Java, and even if the correct access modifiers are used, they cannot be exposed outside the class.

Since this topic is so hot, I recommend some advanced reading to you: Heinz Kabutz’s crazy speech about reflection technology at the 2009 JavaZone conference. This article covers common problems in reflection operations, as well as other content about reflection technology. . This article is very good and very crazy.

This article reveals why reflection techniques are useful in certain scenarios, but in most cases you should avoid using it.

Answer #2:

In Java, if two variables of type String are initialized to the same string, then both variables will be assigned the same object reference. This is why the expression "Test1==Test2" returns true.

String Test1="Hello World";
String Test2="Hello World";
System.out.println(test1==test2); // true

Is the String object in java mutable?

Test3 is a new String object created by the substring() method. It does not share the same value array with Test1. (Note: Due to a clerical error by the original author, the first letters of the variables test1 and test3 in the picture below are not capitalized. Please pay attention to the readers)
We can access the String object through reflection technology and obtain the pointer of the value array:

Is the String object in java mutable?

Field field = String.class.getDeclaredField("value");
field.setAccessible(true);

Change The value of this value array can change the value of all String objects holding the array pointer, so the values ​​of Test1 and Test2 have changed. But since Test3 is a new String object created by the substring() method, its value has not been changed.

Is the String object in java mutable?


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn