String immutability, Long cache source code analysis and interview questions

String immutability, Long cache source code analysis and interview questions

Everyone is familiar with String and Long. Now let’s take a look at the underlying source code implementation of String and Long in combination with actual work scenarios. See if there are any points that we need to pay attention to when we use them, and summarize what these APIs are applicable to. Scenes.

One: String

1.1. Immutability

We often see such interview questions: Please briefly talk about the difference between String, StringBuilder and StringBuffer. Among them, String is different from the other two. Once the String value is initialized, it cannot be changed. If it is modified, it will be a new class. Let's take a look at the following piece of code. Although "ssssss" will be output at the end, it seems that the value of String has been modified.

String str = "aaa";
str = "ssssss";
System.out.println(str);

In fact, we can see intuitively through Debug that the value of String has not been modified.
String immutability
String immutability
At first, the memory address pointed to by str is 527, and after a round of assignment, the memory address pointed to by str becomes 529. In other words, the seemingly simple assignment of str = "ssssss" actually points the reference of str to the new String.

Now we look at the reason from the source code of String

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    
    /** The value is used for character storage. */
    private final char value[];
}    

We can see from the source code of String:

  1. String is modified by final, indicating that the String class will never be inherited, that is to say, any operation method on String will not be overwritten by inheritance ;
  2. The data stored in String is a char array value. We found that the value is also modified by final, which means that once the value is assigned, the memory address is absolutely impossible to modify, and the permission of the value is private, absolutely inaccessible from the outside, and String has not opened up the assignment of value Method, so once the value is generated, the memory address cannot be modified at all ;

The above two points are the reason for the immutability of String. It makes full use of the characteristics of the final keyword. If you want to be immutable when you customize the class, you can also imitate these two operations of String.

1.2, equality judgment

We have two ways to judge equality, equals and equalsIgnoreCase. When the latter is judged to be equal, the case will be ignored. If you are asked to write the logic to judge the equality of two Strings, how to write it, let's take a look at the source code of equals:

public boolean equals(Object anObject) {
    
    
    // 判断内存地址是否相同
    if (this == anObject) {
    
    
        return true;
    }
    // 待比较的对象是否是 String,如果不是 String,直接返回不相等
    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;
}

As can be seen from the source code of equals, the logic is very clear, and the equivalent code is written completely based on the underlying structure of String. This also provides us with a way of thinking: if someone asks how to judge whether the two are equal, we can start from the underlying structure of the two, so that we can quickly think of a practical idea and method, just like the underlying String The data structure is the same as the char array. When judging the equality, just compare the characters in the char array one by one to see if they are equal.

Two: Long

2.1, cache

We are most concerned about Long’s caching problem. Long has implemented a caching mechanism that caches all Long values ​​from -128 to 127. If it is a Long value in this range, it will not be initialized, but Take it from the cache, the cache initialization source code is as follows:

private static class LongCache {
    
    
    private LongCache(){
    
    }
    // 缓存,范围从 -128 到 127,+1 是因为有个 0
    static final Long cache[] = new Long[-(-128) + 127 + 1];

    // 容器初始化时,进行加载
    static {
    
    
        // 缓存 Long 值,注意这里是 i - 128 ,所以再拿的时候就需要 + 128
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

Three: interview questions

3.1. Why is it recommended to use the valueOf method more and the parseLong method less when using Long?

Because Long itself has a caching mechanism that caches Longs in the range of -128 to 127, the valueOf method will get the value from the cache. If the cache is hit, it will reduce resource overhead. The parseLong method does not have this mechanism.

3.2. Why do everyone say that String is immutable?

If both String and the char array that holds the data are modified by the final keyword, they are immutable. For details, please refer to the above.

Three: Summary

String and Long are used frequently in our work. In the interview process, the examiner also likes to ask some practical questions to check our proficiency.

Guess you like

Origin blog.csdn.net/weixin_38478780/article/details/107762049