Java Interview Alchemy Series (1) | Analysis of common interview questions about String

for example:

public static void main(String[] args) {
    //基本数据类型
    int num1 = 100;
    int num2 = 100;
    System.out.println("num1 == num2 : " + (num1 == num2) + "\n");

    //引用类型,其中'System.identityHashCode'可以理解为打印对象地址
    String str1 = "mio4";
    String str2 = "mio4";
    System.out.println("str1 address : " + System.identityHashCode(str1));
    System.out.println("str2 address : " + System.identityHashCode(str1));
    System.out.println("str1 == str2 : " + (str1 == str2) + "\n");

    String str3 = new String("mio4");
    String str4 = new String("mio4");
    System.out.println("str3 address : " + System.identityHashCode(str3));
    System.out.println("str4 address : " + System.identityHashCode(str4));
    System.out.println("str3 == str4 : " + (str3 == str4));
}

Run the above code, you can get the following results:

num1 == num2 : true

str1 address : 1639705018
str2 address : 1639705018
str1 == str2 : true

str3 address: 1627674070
str4 address: 1360875712
str3 == str4: false
You can see that the memory addresses of str1 and str2 are both 1639705018, so use == to judge as true,

But the addresses of str3 and str4 are different, so the judgment is false.

  1. equals() method
    2.1 Object class equals()
    In the Java language, all classes inherit from the Object superclass. There is also an equals() method in this class, so let’s take a look at this method first.

It can be seen that this method is very simple, it is to compare the memory address of the object. Therefore, when the object does not override this method, this method is used by default, that is, the memory address value of the object is compared. But classes like String and Integer have rewritten equals(). Take String as an example below.

2.2 String class equals()

Obviously, the equals() method of String only compares its data value, not the memory address of the object.

Take String as an example to test:

public static void main(String[] args) {
String str1 = “mio4”;
String str2 = “mio4”;

    String str3 = new String("mio4");
    String str4 = new String("mio4");

    System.out.println("str1 address : " + System.identityHashCode(str1));
    System.out.println("str2 address : " + System.identityHashCode(str1));
    System.out.println("str1.equals(str2) : " + str1.equals(str2) + "\n");

    System.out.println("str3 address : " + System.identityHashCode(str3));
    System.out.println("str4 address : " + System.identityHashCode(str4));
    System.out.println("str3.equals(str4) : " + str3.equals(str4) + "\n");
}

The test output is as follows. It can be seen that the addresses of str3 and str4 are different, but because the contents of the String string are the same, the equals judgment is true

str1 address : 1639705018
str2 address : 1639705018
str1.equals(str2) : true

str3 address: 1627674070
str4 address: 1360875712
str3.equals(str4): true
3. hashCode() method
3.1 Why is there such a method? Usage scenarios
in Java collection (Collection) There are three types, one is List, one is Queue, the elements in the set is ordered, the element can be repeated; then there is a class of Set, a disorderly elements within the set, but Elements cannot be repeated.

So, here is a more serious problem: if you want to ensure that the elements are not repeated, what should be the basis for judging whether two elements are repeated? This is the Object.equals method. However, if the check is performed every time an element is added, when there are many elements, the number of comparisons of the elements added to the set will be very large. In other words, if there are already 1000 elements in the collection, when the 1001st element is added to the collection, it will call the equals method 1000 times. This will obviously greatly reduce efficiency. Therefore, Java uses the principle of hash tables. In this way, we use a hash algorithm to calculate a value for each element to be stored in the set, and then calculate the position of the element in the array based on the value. Therefore, when a new element is added to the collection, it can be divided into two steps:   
first call the hashCode method of this element, and then calculate the position of the element in the array based on the obtained value. If there is no element at this position, then directly store it at this position;
if there is already an element at this position, then call its equals method to compare with the new element: if it is the same, it will not be stored, otherwise, it will be stored This position corresponds to the linked list (the implementation of HashSet, HashMap and Hashtable in Java always put the elements at the head of the linked list).
3.2 The association between hashCode() and equals()
 Premise: When it comes to hashCode, you have to say equals method, both of which are methods in the Object class. Since the Object class is the base class of all classes, these two methods can be overridden in all classes.

Principle 1: If x.equals(y) returns "true", then the hashCode() of x and y must be equal;
Principle 2: If x.equals(y) returns "false", then the hashCode() of x and y have It may be equal or not;
Principle 3: If the hashCode() of x and y are not equal, then x.equals(y) must return "false";
Principle 4: Generally speaking, the equals method is called for users , And the hashcode method is generally not called by users;
Principle 5: When an object type is used as an element of a collection object, then this object should have its own equals() and hashCode() design, and it must comply with the aforementioned several in principle.
In summary, the things to note are:

Two objects with
equals equals , hashCode must be equal Two objects with unequal equals method, hashCode may be equal to
0x1 Frequent interview questions

  1. Have you seen the String source code? Why use final modification?
    public final class String
    implements java.io.Serializable, Comparable, CharSequence {}
    Core explanation:

​ 1. To achieve string pool

​ 2. For thread safety

​ 3. In order to achieve String immutability can be created HashCode

The final modified String represents the non-inheritability of String, and the final modified char[] represents the unchangeability of the stored data. But: Although final represents immutability, but just the reference address is immutable, it does not mean that the array itself will not change.
Final can also change the array itself. At this time, private is also useful, because the two guarantee the immutability of String.
So why ensure that String is immutable, because only when the string is immutable, the string pool can be realized. The implementation of string pool can save a lot of heap space at runtime, because different string variables all point to the same string in the pool. But if the string is variable, then String.intern() will not be implemented, because in this case, if the variable changes its value, the values ​​of other variables pointing to this value will also change.
Because the string is immutable, the HashCode is cached when it is created and does not need to be recalculated. This makes the string very suitable as a key in the Map, and the processing speed of the string is faster than other key objects. This is that the keys in HashMap often use strings.
2. What are the initialization methods of
String ? The initialization of String type is divided into two types in Java:

One type is initialized by wrapping a character in double quotation marks; the
other type is to initialize a String instance like an ordinary object through the keyword new.
The former opens up a constant in the constant pool l and returns the corresponding reference, while the latter opens up a constant in the heap and then returns the corresponding object. Therefore, the reference of the two is definitely different:

public static void main(String… args) { String s1 = "abcd"; String s2 = new String("abcd"); System.out.println(s1 == s2); // false } And the constants in the constant pool It can be shared to save memory overhead and creation time overhead (this is also the reason for the introduction of constant pool), for example:




public static void main(String… args) { String s1 = "abcd"; String s2 = "abcd"; System.out.println(s1 == s2); // true } Combining the two, you can actually answer another A common interview question:




public static void main(String... args) { String s = new String("abcd"); }How many objects does this sentence create?


First of all, there is no doubt that "abcd" itself is an object, which is placed in the constant pool. Since the new keyword is used here, the object obtained by s must be created in the heap. So, there are actually 2 objects created here.

It should be noted that if the string "abcd" already exists somewhere else before this function is called, then it has been created in the constant pool in advance. At this time, only one object will be created here, that is, the new String ("abcd") object created in the heap.

  1. Is String thread safe?
    String is an immutable class. Once a String object is created, we cannot change its value. Therefore, it is thread-safe and can be safely used in a multi-threaded environment.

  2. Why do we often use String as the key when using HashMap?
    Because a string is immutable, when a string is created, its hashcode is cached and does not need to be calculated again. Because the internal implementation of HashMap uses the hashcode of the key to determine the storage location of the value, it is faster than other objects. This is why we usually use String as the HashMap object.

  3. What is the intern() method of String?
    The String.intern() method can add constants to the constant pool during runtime. The way it works is:

If there is a constant in the constant pool that is exactly equal to the value of this string, the intern() method returns a reference to the constant that exists in the constant pool.
If there is no constant in the constant pool that happens to be equal to the value of this string, a new constant is created in the constant pool and the value of this string is assigned to the newly created constant in the constant pool. The intern() method returns a reference to this newly created constant.
Example:

public static void main(String… args) {
String s1 = “abcd”;
String s2 = new String(“abcd”);

/**
 * s2.intern() will first search String constant pool,
 * of which the value is the same as s2.
 */
String s3 = s2.intern();
// As s1 comes from constant pool, and s3 is also comes from constant pool, they're same.
System.out.println(s1 == s3);
// As s2 comes from heap but s3 comes from constant pool, they're different.
System.out.println(s2 == s3); 

}

/**

  • Output:
  • true
  • false
    */
    Recalling the first part of the beginning, why introduce the intern() function? This is because although "abcd" is allocated in the constant pool, once new String ("abcd") is used, a new object with the value abcd will be created in the heap. Just imagine, if there are 100 such sentences, isn't it necessary to create 100 objects of the same value in the heap? ! This results in inefficient operation and waste of space.

Therefore, if intern() is introduced, it will go directly to the constant pool to find whether there are String objects with the same value, which greatly saves space and improves operating efficiency.

  1. Some programming questions about the constant pool (1)
    String s1 = "ab";
    String s2 = "abc";
    String s3 = s1 + "c";

System.out.println(s3 == s2); //false is not equal, s1 is a variable, the value cannot be determined when compiling, the value will be created in the memory, and s3 is in the heap memory. s2 is in the constant pool, so it is not equal.
System.out.println(s3.equals(s2)); //true compares the values ​​of two objects for equal value.
Explanation of the above code:

String s1 = “abc”; String s2 = “abc”;

s1 will be created in the constant pool, s2 will first check if there is any in the constant pool, if so, point to it, if not, create one in the constant pool and point to it. So the two comparisons of s1 and s2 are the same.

  1. Some programming questions about the constant pool (2)
    String s1 = new String("Hello");
    String s2 = new String("Hello"); The
    answer is 3 objects.

First, line 1 is the "hello" object in the string pool.

Second, line 1, a new string with the value "hello" in the heap memory.

Third, line 2, a new string with "hello" in the heap memory. Here the strings in the "hello" string pool are reused.

  1. Talk about the difference between String, StringBuffer and StringBuilder?
    String is an immutable class. Whenever we operate on String, a new string is always created. Operating String is very resource intensive, so Java provides two tool classes to manipulate String: StringBuffer and StringBuilder.
    StringBuffer and StringBuilder are mutable classes, StringBuffer is thread-safe, StringBuilder is not thread-safe. Therefore, when multiple threads operate on the same string, we should choose StringBuffer. Because there is no need to deal with multithreading, StringBuilder is more efficient than StringBuffer.
    Amazon review www.yisuping.com

Guess you like

Origin blog.csdn.net/weixin_45032957/article/details/108599271