I am kite, the public account “ancient time kite”, a not only technology public account, I have been in the app community for many years, mainly Java, Python, React also play 6 slash developer. The Spring Cloud series is complete, and you can check out the full series on my Github. You can also reply “PDF” in the public account to get the full PDF version of my elaborate tutorial.

The string question is one of the most enduring questions in Java, especially when it comes to string constant pools. However, there are still a lot of students who only know a little about the seemingly simple and often mentioned problem. They seem to understand it, but they find that they do not understand it after careful analysis.

The background that

This article uses JDK 1.8 as the discussion version, but we still love 1.8 even though it’s JDK 14 now.

A discussion triggered by a question

Why do we talk about string constants? It comes from the question of one of the few programmers in the group.


It doesn’t have anything to do with String constants, but then one of the students said, not just int, but String.


Why would there be such a strange string “Java development _ Beijing “, because the group nickname of the little sister who asked the question is called this, so the students in the group joked that they thought she was a real estate tycoon, to develop Beijing.


I was just kidding. All right, take it.

String comparisons with == are also true, which is interesting. The string constant pool has something to do with it. Yes, because of the string constant pool.

JDK 1.8 does not allow Object and int to be compared with ==.

The code in the second figure is the main point, and we can simplify it to the following lines, which compare strings with the == symbol. The rest of the story starts with these lines.

public static void main(String[] args) {

   String s1 = "Ancient Kites.";

   System.out.println(s1 == "Ancient Kites.");

}

Copy the code

Of course, using the == symbol to determine whether two strings are equal is strongly discouraged in practice. Instead, use equals().

String constant pool

Why should there be a pool of string constants, stored in the heap like any other object, is a question for the Java language designers, and of course, it was not a brainchild.

It starts with strings.

The distribution of the first object to pay on time and space of overhead, the string is commonly used types and 8 basic types, and even more common than eight basic types, so often create a string object, the performance impact is very big, so, in the constant pool way can largely reduce the number of object creation, distribution, This improves performance.

After JDK 1.7 (including 1.7), the string constant pool has been moved from the method area to the heap.

Literal assignment

Let’s get the example code above

String s1 = "Ancient Kites.";

Copy the code

This is the most common way to declare a string variable. It’s called a literal declaration, which is to enclose the string in double quotes and assign it to a variable.

In this case the string is placed directly into the string constant pool and returned to the variable.


So if I declare a string with the same content, it’s already in the string constant pool, so it just points to the address in the constant pool.


For example, as shown in the figure above, s1 and s2 are declared to refer to the same constant pool address, so s1== s2 results in true.

New String () method

The alternative is to use the new String() method, but it is generally not recommended unless there is special logic to do so.

String a = "Ancient";

String s2 = new String(a + "The kite");

Copy the code

When you declare string variables in this way, two things happen.

In the first case, the string constant pool already has the same string

For example, if a variable has been declared as a literal before using new, there are already string constants with the same content in the string constant pool.

  1. An object reference to the s2 variable is first created in the heap;
  2. This object reference then points to an existing constant in the string constant pool;
In the second case, there is no constant with the same content in the string constant pool

This String hasn’t been used anywhere before, so the first time you declare this String is new String(), in which case you create a String object directly in the heap and return it to the variable.


I’ve seen a lot of places that say if the String constant pool doesn’t exist, put the String first and then reference the constant object in the String constant pool. This is a problem, but if a new String() doesn’t exist, it won’t put a copy in the pool.

Based on this property of new String(), we can draw a conclusion:

String s1 = "Ancient Kites.";

String a = "Ancient";

String s2 = new String(a + "The kite");

String s3 = new String(a + "The kite");

System.out.println(s1==s2); // false

System.out.println(s2==s3);  // false

Copy the code

All of this code, I’m sure, is going to print false, because new String() whether you have a constant pool or not, I’m going to create a new object in the heap, and the new object, of course, is not going to be equal to the other objects.

The intern () pooling

So when do you put it in the string constant pool, after you use intern().

Intern () : If the current string content exists in the string constant pool, it exists only if the equas() method is true, that is, the content is the same. If not previously in the string constant pool, a reference is created in the constant pool and points to an existing string in the heap, then the address in the constant pool is returned.

In the first case, the string to be pooled is identical to the string in the string constant pool (equas() judgment)
String s1 = "Ancient Kites.";

String a = "Ancient";

String s2 = new String(a + "The kite");

s2 = s2.intern();

Copy the code

At this point, the string constant already exists in the constant pool, a new object s2 is created, and an object with the same string content is created in the heap.


In this case, s1 == s2 returns fasle. Then we call s2 = s2.intern() and assign the pooled result to S2, and the following changes occur.


When s1 == s2 is checked again, it returns true because they both refer to the same string in the string constant pool.

In the second case, there is no string with the same content in the string constant pool

A String object is created in the heap using new String()


What happens after you use intern() is that you add an object to the constant pool, but instead of copying the string into the constant pool, you point directly to the string object that was already in the heap. After JDK 1.7, string constant pools may not necessarily store string objects, but may also store a reference to an address in the heap. Note that s2.intern() is only called and does not return a variable. Where the string constant pool (0x88) points to the procedure of the string object (0x99) in the heap, which is intern().


S2 actually refers to the string constant pool only if we return the result of s2.intern() to S2.


I’ve learned

With that said, what does the following piece of code return

public class Test {



    public static void main(String[] args) {

        String s1 = "Ancient Kites.";

        String s2 = "Ancient Kites.";

        String a = "Ancient";

      

        String s3 = new String(a + "The kite");

        String s4 = new String(a + "The kite");

        System.out.println(s1 == s2); // 【1】 true

        System.out.println(s2 == s3); // 【2】 false

        System.out.println(s3 == s4); // 【3】 false

        s3.intern();

        System.out.println(s2 == s3); // 【4】 false

        s3 = s3.intern();

        System.out.println(s2 == s3); // 【5】 true

        s4 = s4.intern();

        System.out.println(s3 == s4); // 【6】 true

    }

}

Copy the code

[1] : s1 == s2 returns true because they are literal declarations and all refer to the same string in the string constant pool.

[2] : s2 == s3 returns false because new String() is a new object in the heap, so it is not the same as the constant pool constant.

[3] : s3 == s4 returns false, both objects are created in the heap, so they must be different.

[4] : s2 == s3 returns false.

[5] : s2 == s3 returns true, and calls intern() and returns s3, where s2 and s3 refer directly to the same string in the constant pool.

[6] : s3 == s4 returns true.

Why is my string immutable

A constant pool of strings is based on the immutability of strings. If strings were mutable, come to think of it, there would be no need for constant pools. Suppose that multiple variables all refer to the same string in the string constant pool, and then, suddenly, a line of code changes the string, no matter what, that would be a mess for the JVM.

The root reason for immutable strings should be security.

We know that JVM types are loaded with class names, such as java.lang.String. If the String is mutable, I can replace it with other characters.

The project will use strings such as database connection string, account number, password and so on. Only immutable connection string, user name and password can ensure security.

Strings are used very frequently in Java, and immutability allows strings to be read and written without considering multithreaded contention in the case of high concurrency.

There is also HashCode, which is the core condition for judging whether two objects are exactly equal. In addition, key values in Set and Map structures also need HashCode to ensure uniqueness and consistency. Therefore, immutable HashCode is secure and reliable.

Finally, as mentioned above, frequent creation of string objects imposes performance overhead, so immutability is used to create a string constant pool to ensure performance.

The latter

Know what is, and know what is. A little knowledge is not the goal we seek. I don’t know if the picture is clear enough, I hope it can help students who are not familiar with the string constant pool.

Creation is not easy, small praise, big warm, warm me quickly. Praise me!!!!!!! Don’t stand on ceremony.

I am kite, public id “ancient Time kite”, I have been working in the application circles for many years, mainly Java, Python, React also play very 6 slash developer. Can add my friends in the public account, into the group of small partners exchange learning, a lot of dachang students are also in the group yo.