What does STRING compare using the EQUALS method and == respectively? (Turn)

The difference between the equals method used by String and ==

Difference between equals method and ==
  First of all, as we all know, String can be used both as an object and as a primitive type. The use as a basic type here only refers to the method of use, such as String s = "Hello", its use method is the same as the basic type int, such as int i = 1;, and as an object, it is Refers to creating a new object through the new keyword, such as String s = new String("Hello"). But its internal action actually creates an object, which will be discussed later.
 
        Second, the comparison methods of String objects need to be understood. There are two concepts for the comparison between objects in Java. Take String objects as an example: one is to use "==" to compare, which is a reference to two variables of type String, that is to say, if two For variables of type String, they refer to the same String object (that is, point to the same memory heap), the result of the "==" comparison is true. The other is to use the equals() method of the Object object to compare. The String object inherits from Object and overrides the equals() method. When two String objects are compared by the equals() method, they are actually comparing the contents of the strings encapsulated by the String objects, that is to say, if the contents of the strings encapsulated by the two String objects are the same (including the same case), Then the equals() method will return true.
 
Now start to make a specific analysis of the creation of String objects:
 
1、/////////////////////////////////////////////////////////////////////////
String s1 = new String("Hello");
String s2 = new String("Hello");
 
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
 
The print result of the above code snippet is:
 
false
true
 
        This result is believed to be well understood by everyone. The two String-type variables s1 and s2 both create a new String object through the new keyword. The new keyword allocates a new and independent memory heap for each object created. . So when using "==" to compare whether they refer to the same object, it will return false. When compared by the equals() method, it returns true because the string content encapsulated by the two objects is exactly the same.
 
2、//////////////////////////////////////////////////////////////////////////////////
String s1 = new String("Hello");
String s2 = s1;
 
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
 
The print result of the above code snippet is:
 
true
true
 
        This result should be better understood. The variable s1 still uses the new keyword to create a new String object, but here s2 does not use the new keyword to create a new String object, but directly assigns s1 to s2. That is, the reference of s1 is assigned to s2, so the object referenced by s2 is actually the object referenced by s1. So when comparing by "==", return true. Since they all refer to the same object, they must return true when they are compared by the equals() method. Here, the equals() method is actually comparing the same object, and it must be equal to itself.
 
3、//////////////////////////////////////////////////////////////////////////////
String s1 = "Hello";
String s2 = "Hello";
 
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
 
The print result of the above code snippet is:
 
true
true
 
        Why this result? So let's analyze it. First of all, these two String objects are used as a basic type, not created by the new keyword, so the virtual machine will not allocate a new memory heap for these two String objects, but to the String buffer pool. to find.
 
        First, find out whether there is a String object with the same value as "Hello" in the String buffer pool for s1. At this time, the String buffer pool is empty, and there is no String object with the same value. Therefore, the virtual machine creates this String object in the String buffer pool. The action is new String("Hello");. Then assign a reference to this String object to s1.
 
        Then search for s2 whether there is a String object with the same value as "Hello" in the String buffer pool. At this time, the virtual machine finds a String object with the same value. This String object is actually the String object created for s1. Since an object of the same value is found, the virtual machine does not create a new String object for this, but directly assigns the reference of the existing String object to s2.
 
        Here, since s1 and s2 refer to the same String object, that is, they are equal to themselves, so the above two comparison methods both return true.
 
        At this point, the basic concepts of String objects should be understood. Now let me summarize:
 
Use String as a primitive type:
 
1. If String is used as a primitive type, then we consider this String object to be owned by the String buffer pool.
2. If String is used as a basic type and there is no String object with the same specified value in the String buffer pool at this time, the virtual machine will create a new String object for this and store it in the String buffer pool.
3. If String is used as a basic type, and a String object with the same value as its specified value exists in the String buffer pool at this time, the virtual machine will not create a new String object for this, but directly returns a reference to the existing String object.
 
To use String as an object:
 
1. If String is used as an object, the virtual machine will create a new String object for this, that is, allocate a new memory heap for this object, and it is not owned by the String buffer pool, that is, it is independent.
 
Once you understand the above, take a look at the following code snippet:
4、/////////////////////////////////////////////////////////////////////////////
String s1 = "Hello";
String s2 = new String("Hello");
 
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
 
The print result of the above code snippet is:
 
false
true
 
        Analyze according to the above summary. The first line uses String as a basic type, so the object referenced by s1 belongs to the String buffer pool. And there is no String object with the same value in the String buffer pool at this time, so the virtual machine creates a new String object for this, namely new String("Hello");. The second line uses String as an object, so the object referenced by s2 does not belong to the String buffer pool, that is, it is independent. Through the new keyword, the virtual machine creates a new String object for this, that is, allocates a new memory heap for it. Therefore, the result of the "==" comparison is false, because s1 and s2 do not refer to the same object, they exist independently. The equals() method returns true because the string content encapsulated by the two objects is exactly the same.
 
        Now, I believe that everyone has completely figured out what the String object is all about :) But this is not the end, because the String object has a deeper application.
 
        Here I will analyze the application of the intern() method of the String object:
The intern() method will return the canonical representation of a String object, a String with the same contents as the String, but from a String buffer pool of unique Strings. This may sound a bit tricky, but it actually works like the following code snippet:
 
String s = new String("Hello");
s = s.intern();
 
The function implementation of the above code segment can be simply viewed as the following code segment:
 
String s = "Hello";
 
        You must be starting to wonder again? Then you can look at the second code snippet first. The meaning of the second code segment is to take a reference to a String object with the same value from the String buffer pool and assign it to s. If no String object with the same value exists in the String buffer pool, a new String object is created for it in it. So what does the first piece of code mean? We know that the object created by the new keyword, the virtual machine allocates a new memory heap for it. If you trivially create an object with the same content, the virtual machine will also allocate many new memory heaps for this, even though their content is exactly the same. Take String objects as an example, if 10 String objects with the same content are created in a row (new String("Hello" )), then the virtual machine will allocate 10 separate memory heaps for this. Assuming that the string content of the created String object is very large, assuming that a Stirng object encapsulates the string content of 1M size, then if we create 10 of these same String objects, we will waste 9M memory space meaninglessly . We know that String is a final class, and it encapsulates string constants, so the internal (string) value of a String object cannot be changed after it is created, so String objects can be shared. So for the assumption just mentioned, we created 10 String objects with the same content, in fact, we only need to create a String object for this, and then be shared by other String variables. To implement this mechanism, the only and simple way is to use the String buffer pool, because there will be no String objects with the same content in the String buffer pool. The intern() method is the way to use this mechanism. After calling the intern() method on an instantiated String object, the virtual machine looks for a String object with the same value as the string content encapsulated by the Stirng object in the String buffer pool, and then assigns the reference to the original String object. variable of type String. If there is no String object with the same value as the string content encapsulated by this String object in the String buffer pool, then the virtual machine will create a new String object for this, and assign its reference to the String type variable that references the original String object . In this way, the purpose of sharing the same String object is achieved, and the original String object created by the new keyword will be discarded and recycled by the garbage collector. This not only reduces memory consumption and improves performance, but also makes the comparison of String objects more convenient, because the same String objects will be shared, so to judge whether two String objects are the same, you only need to use "" === to compare, instead of using the equals() method to compare, which is not only more convenient to use, but also improves performance, because the equals() method of the String object will disassemble the string content, and then perform one by one. Comparison, if the string content is very large, then this comparison action will greatly reduce the performance.
 
        Having said that, you may still be a little vague about the specific application, so let me give a simple example to illustrate the above concepts:
 
        Suppose there is a class that has a method for logging messages. This method records messages from users (assuming the message content may be large and has a high repetition rate), and records the messages in a list in the order they are received. I think some friends will design it like this:
 
import java.util. *;
 
public class Messages {
 
ArrayList messages = new ArrayList();
 
public void record(String msg) {
messages.add(msg);
}
 
public List getMessages() {
return messages;
}
}
 
        Is this design good? Suppose we repeatedly send the same message to the record() method (messages come from different users, so each message can be regarded as a new String("...")), and the message content is large, then this design will A huge waste of memory space, because the message list records are newly created, independent String objects, although their content is the same. So how can we optimize it? It's actually very simple. Please see the following optimized example:
 
import java.util. *;
 
public class Messages {
 
ArrayList messages = new ArrayList();
 
public void record(String msg) {
messages.add(msg.intern());
}
 
public List getMessages() {
return messages;
}
}
 
        As you can see, the message.add(msg); code segment in the original record() method has become messages.add(msg.intern());, and only the intern() method is called on the msg parameter, so that There will be a sharing mechanism for duplicate messages, which reduces memory consumption and improves performance.
 
This example is indeed a bit far-fetched, but it's just here to illustrate the above concept!
 
So far, the fog of String objects has been eliminated. As long as you keep these concepts in mind, all complex String applications in the future can be analyzed on this basis.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326075399&siteId=291194637