In-depth String storage-difference between equals and ==

For equals and ==, I think everyone is very familiar with it. To start with, the parent class Object of all classes has the equals method in it, and the implementation inside is ==.

However, objects have three major characteristics, encapsulation, inheritance, and polymorphism. After many classes inherit the Object class, they encapsulate different attributes as needed. Naturally, you can’t directly perform ==. This is just a comparison of addresses, meaningless, so various Subclasses have their own implementations. For example, equals in Date class compares time, equals in HashMap Node<K,V> compares addresses, and also compares values. If any one is the same, it returns true.

Of course, we usually encounter more equals and == in String. But to be honest, whoever uses == in the code uses equals, nothing to say, safe!

Let's take a look at the implementation of equals in String:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

This code is not difficult. It first compares whether the two strings are the same, compares the addresses, and then compares whether the value arrays in the String are the same. As long as one of the two conditions is true, equals returns true.

In fact, everyone knows that writing code will not cause bugs in equals in String. Why are so many people keen to distinguish equals from ==? I often ask questions in interviews, otherwise, who will go to the roots and panic?

The estimation that the most elementary rookie encounters is what equals and == in String, what is the difference, can they be interchanged? what? The answer is easy to see in the source code,

Then it grows a little bit, just to judge whether the == of a few Strings is true or false.

Later, in the appetizers of the interview, you may encounter questions about String storage.

Let's talk about the judgment of String storage and equality.

Everyone knows the underlying storage structure of JMM, which is simply divided into heap memory, stack memory, method area, constant pool, registers and the like. Today we are focusing on String, so we mainly study heap memory, stack memory, and constant pool!

In fact, the constant pool is also an area opened up in the heap memory, and the storage of data is mainly in the heap memory.

Let's take a look at the process of String creation and storage.

String str = new String("abc");

Create a new String object and complete the assignment abc. What kind of creation process did it go through?

First of all, this operation will definitely generate an "abc" string. Create a new str in the memory stack as a reference to the object.

Next, the heap memory is created, and a String object with a value of "abc" is created. Finally, it is to check whether there is an "abc" string in the constant pool, if not, create a new one, if there is, ignore it.

This is a simple creation process, so good, now we look at a specific example:

 

As shown in the figure above, 5 objects have been created, and we will look at them one by one.

The first one is to create an object reference s1, create an "abc" in the constant pool, an object should also be created in the heap memory, but there is no reference, the next GC will be recycled.

Second, an object reference s2 is created, an object is created in the heap, "abc" is already in the constant pool, and it is not being created.

Third, a reference s3 of an object is created, "a", "bc" and "abc" are created in the heap, but there are no references to "a" and "bc", and gc will be recycled next time. "Abc" in the constant pool already exists and will not be created, "a" and "bc" will be created, but there is no reference, and will be recycled soon.

Fourth, an object reference s4 is created, an object is created in the heap, there is already "abc" in the constant pool, and it is not being created, and then the string in the constant pool is obtained using the intern() method.

Fifth, a reference s5 of an object is created. An object is created in the heap, but it is not referenced and points directly to the string in the constant pool.

Obviously, both s1 and s5 point to "abc" in the constant pool, and intern() points to the object created by the string "abc" for the first time, which is the same data, and the result of using == is also true.

s2, s3, and s4 are all an object, and the result of using == must be false.

Maybe some friends are a little confused, s4 also points to the "abc" in the constant pool, why can't it be == with s1?

Okay, let's take a look at the source code of intern():

public native String intern()

Well, only this line is a native method, and the bottom layer is not implemented by java. But it doesn't matter, we can find the result we want from this line.

Let's take a look at the creation process of s4. First, a string of s4 is created, and then s4.intern(). Then there is a relationship between s4.intern() and s4? Isn't it good to get a constant pool string? And there is no assignment yet. The intern() method obviously has a return value, is it good? Your return value is not assigned. This code s4.intern() is almost a waste of good, but it is clear: I will interfere with you, why?

Well, let's run it and have a look:

public class Test {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = new String("abc");
        String s3 = new String("a")+ new String("bc");
        String s4 = new String("abc"); s4.intern();
        String s5 = new String("abc").intern();
        System.out.print("s1==s5的结果");
        System.out.println(s1==s5);
        System.out.print("s1==s2的结果");
        System.out.println(s1==s2);
        System.out.print("s1==s3的结果");
        System.out.println(s1==s3);
        System.out.print("s1==s4的结果");
        System.out.println(s1==s4);
        System.out.print("s3==s4的结果");
        System.out.println(s3==s4);
    }
}

The result is of course the same as expected. Besides, don’t look at me writing a description and the result is divided into two lines. That is to use the "+" sign to connect the string first, and then compare, then don’t play anything, hehe, I I have passed the most advanced stage, and I have advanced to a more advanced rookie. Okay, let’s see the result:

com.example.demo.Test
s1==s5的结果true
s1==s2的结果false
s1==s3的结果false
s1==s4的结果false
s3==s4的结果false

Process finished with exit code 0

Interested students can debug it, and you will find that this creation string has an address. It is easy to see how it is.

Okay, let's stop here today~

Guess you like

Origin blog.csdn.net/zsah2011/article/details/105421652