How many objects are created by analyzing new String()? And what is the difference between string objects created in different ways?

Today I saw a very interesting high-frequency interview question, the content of which is really interesting, let's talk about it, first look at a few interview questions, try the level;

Table of contents

Interview question type 1:

Interview question type 2:

 explain:

At present, there are 3 answers about the number of objects created by new String("xxx"):

  First review the "string constant pool":

Let's take a look at how the JVM handles the first two codes in Type 1 of interview questions:

Introduction of new knowledge:

Implementation principle of using + to splice strings


Interview question type 1:

Execute the following codes respectively: Please answer how many string objects are created during the execution of them ?

Code 1: new String("xxx");//one or two

Code 2: String str = "abc" + "def";//0 or one

Code three: String s=new String(“xxx”);//one or two

Code 4: String str = "abc" + new String("xxx");//5 pieces

Interview question type 2:

Answer If the following codes are executed, what are the results returned respectively?

String s1 = "Java";
String s2 = "Java";
System.out.println(s1 == s2);//true
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s==s1);//false
String s1 = new String("javaer-wang");
String s2 = new String("javaer-wang");
System.out.println(s1 == s2);//false
String s1 = "abc";
String s2 = new String("def");
String s3 = s1 + s2;
String s4 = "abcdef";
System.out.println(s3==s4); //false

 explain:

Next, we explain the interview questions while summarizing the relevant knowledge points;

At present, there are 3 answers about the number of objects created by new String("xxx"):

  1. Some say 1 object is created;
  2. Some say 2 objects are created;
  3. Some say 1 or 2 objects are created.

The key point of controversy with multiple answers is [ string constant pool] . Some say that the new string method will create a string object in the constant pool, and some people say that the new string will not go to the string constant. The pool creates objects, but when the intern() method is called, it will go to the string constant pool to detect and create a string, so what is the actual situation? Let's talk slowly next. . . .

  First review the "string constant pool":

  • The allocation of strings is the same as other object allocations. It takes a lot of time and space. If you need to create a large number of strings frequently, it will greatly affect the performance of the program. Therefore, in order to improve performance and reduce memory overhead, the JVM introduces The concept of the string constant pool (Constant Pool Table).
  • The string constant pool is equivalent to opening up a constant pool space for strings, which is similar to a cache area. For directly assigned strings (String s="xxx"), the existing string constants are preferentially used every time a string is created. The string in the pool, if there is no related string in the string constant pool, the string will be created in the string constant pool first, and then the reference address will be returned to the variable, as shown in the figure below:


Let's take a look at how the JVM handles the first two codes in Type 1 of interview questions:

How does the JVM execute String s="abc"?
        When the JVM executes String s="abc", it will first check whether the string "abc" exists in the constant pool. If it exists, point s1 to the string; if not exists, create a new string "abc" in the constant pool, and then point s to the string. If the same string literal is used in subsequent code, the JVM will reuse the previously created String object instead of creating a new one.

How does the JVM execute new String("abc");
        when executing new String("abc"), the JVM will first check whether the string "abc" already exists in the constant pool, and if so, return the string directly Reference; if it does not exist, create a new String object on the heap and assign the reference of the string "abc" to the object. At the same time, the object will be added to the constant pool, so that the reference to the object can be returned directly the next time it is used.

        You can also understand it this way; new String("abc") is equivalent to new String(String s1="abc"), that is, you must execute String s1="abc" first, and then create a new String object in the heap area.

So now to answer the title of this article, String s=new String("abc") creates 1 or 2 objects, String s="abc" creates 0 or 1 objects.

I saw on a blog that a blogger analyzed the above execution process as:

String s="abc" will first search from the string constant pool (hereinafter referred to as the constant pool), if "abc" already exists in the constant pool, and "abc" must point to a String object in the heap area, then directly set s Just point to this String object;

I don't agree with this sentence (it just represents my point of view) , let's use examples to prove my point of view; 

According to the above statement; the value returned by the following code should be true, we actually execute it to see the result;

String s2="abc";
String s1=new String("abc");
String s3=new String("abc");
System.out.println(s1==s2);//false
System.out.println(s1==s3);//false

 Let's understand the process more closely through an example again (we are looking at an example):

We use drawing to explain the underlying schematic diagram and principle;

 

 The data of String type is stored in the constant pool, and the properties in the heap only store the address of the value in the constant pool!

①    String str1 = "abc"; The statement directly creates a string, which is the most common way to construct a string. This method of direct assignment does not use the new keyword to open up a new address in the heap, but opens up an address in the constant pool. So the reference to str1 is the address 0x01 of the abc string in the constant pool.

②    String str2 = "abc"; also creates a string directly. But because String is a special reference type, the content stored in the constant pool is immutable. When creating a string object, it will first check whether it exists in the constant pool, and if it does not exist, open up a new storage space. At this time, the object abc referenced by str2 is the same as str1, so this is the content that already exists in the constant pool. Str2 will directly refer to the existing string object in the constant pool. So the content of str2 is also the address 0x01 of the abc string in the constant pool.

③    String str3 = new String("abc"); The statement uses new to open up space in the heap, and the string is created by creating an object. str3 points to the address 0x02 of a new space in the heap, which stores the attribute value of the String object. Similarly, when the value of this attribute is assigned to "abc", it will first check whether this content already exists in the constant pool. At this time, abc already exists in the constant pool, so the attribute value stores the address 0x01 of abc in the constant pool .

④   String str4 = new String("abc"); The statement also uses nuw to open up space in the heap, and uses the creation of new objects to create strings. str4 points to the address 0x03 of a new space in the heap, which stores the property value of the String object. Similarly, when the value of this attribute is assigned to "abc", it will first check whether this content already exists in the constant pool. At this time, abc already exists in the constant pool, so the attribute value stores the address 0x01 of abc in the constant pool.

⑤    If you create a string by creating a new object and find that there is no existing string in the constant pool; then the JVM will continue to open up a new space in the constant pool and store the value in it, and the attribute value in the heap is The address of this space.

Source of the above case: https://www.baidu.com/link?url=xlIOX3u9Gv11cc6XlDpWjEIMaDrhaWtKinWiDEle_GNNz-OVvqntCjlr2o9FDVbj&wd=&eqid=a5c4a04300005cce00000003641ad2c6


Then let's explain the code:

Code 2: String str = "abc" + "def";//0 or one

Code 4: String str = "abc" + new String("xxx");//5 pieces

        For code 2, if you don’t know its underlying implementation, you probably think of String str = "abc" + "def" firstly during the execution process, two objects "abc" and "def" are first created and then spliced ​​​​finally Constitute the third object str; however, this is not the case. It is a waste of memory and time for our JVM to frequently create objects, so how does the JVM handle the string splicing using "+"?

        Underlying implementation: Using the + operator to concatenate strings will generate an intermediate object. If it is a thread-safe environment, we will use StringBuffer to concatenate strings, and a thread-unsafe environment will use StringBuilder.

        Summary: The above question involves the overloading of "+" for string constants. When a string is concatenated from multiple string constants into one string, it must be a string constant itself. The "+" sign of the string constant is connected to the Java virtual machine and optimized to the connected value during program compilation. As far as the above example is concerned, it has been merged into the "abcdef" string at compile time, so only 1 object will be created (you can also say two, because stringbuffer or stringbuilder can also be added). Temporary string objects abc and def are not created, which reduces the pressure on the garbage collector;

Introduce a knowledge point:

        When the JVM compiles the code we write, it will optimize the code we write      

After understanding the above example, the fourth example is easy to understand:

        The above code Java virtual machine will also be optimized when compiling, and a StringBuilder will be created to splice strings. The actual effect is similar:

String s = new String("def");
new StringBuilder().append("abc").append(s).toString();

Obviously, there is an extra StringBuilder object, so there should be 5 objects.

        At this point, you may also have such a question, isn't the "abcdef" after the last toString() of StringBuilder stored in the constant pool? This is really not saved, let's take a look at this code:

    String s1 = "abc";
    String s2 = new String("def");
    String s3 = s1 + s2;
    String s4 = "abcdef";
    System.out.println(s3==s4); // false

        According to the above analysis, if the result of s1+s2 is stored in the constant pool, then the value reference in s3 should be the same as the value reference in s4. But the result is very different, it is not stored in the constant pool but stored in the heap memory, the above code will prove this point;

Why is this so? We keep the following concepts in mind:

Only new objects that use "+" connections between string objects created by using quotation marks to contain text will be added to the string constant pool, and for connection methods that contain new string() or null "+" strings The new object generated will not be added to the string constant pool;

To verify the above concepts:

        /*
        String s5="qwe"+"asd";
        String s6="qweasd";
        System.out.println(s5==s6);//true
        */
        String s5="qwe"+new String("asd");
        String s6="qweasd";
        System.out.println(s5==s6);//false

Continue to summarize:

There are essential differences between the two initialization forms of String.

String str1 = "abc"; // in the constant pool

String str2 = new String("abc"); // on the heap

Introduction of new knowledge:

Implementation principle of using + to splice strings

        As mentioned earlier, using + to splice strings is actually just a syntactic sugar provided by Java. Let's see how its internal principles are realized. Still such a piece of code. Let's decompile the bytecode he generated to see the result.

String a = "Hello";
String b = "world";
String c = a + "," + b;

The decompiled content is as follows:

String a = "Hello";
String b = "world";
String c = (new StringBuilder()).append(a).append(",").append(b).toString();

        By looking at the decompiled code, we can find that the original string constant is processed by converting String into StringBuilder and using its append method in the splicing process. That is to say, + is equivalent to append of StringBuilder,

That is to say, the implementation principle of using + to splice strings is to use StringBuilder.append.

In fact, it is also very interesting to look at the underlying implementation of Java knowledge points occasionally. I hope that everyone can have an inquiring learning spirit in their studies; 

I know exactly what I want, what I want to be, what to do, how to do it. But I can't beat myself, so so far I'm still me;

                                                                ——

Guess you like

Origin blog.csdn.net/m0_64231944/article/details/129714801