문자열 불변성, 긴 캐시 소스 코드 분석 및 인터뷰 질문

문자열 불변성, 긴 캐시 소스 코드 분석 및 인터뷰 질문

모두가 String 및 Long에 익숙합니다. 이제 실제 작업 시나리오와 결합하여 String 및 Long의 기본 소스 코드 구현을 살펴 보겠습니다. 사용할 때주의해야 할 사항이 있는지 확인하고 이러한 API가 적용되는 내용을 요약합니다. 장면.

하나 : 문자열

1.1. 불변성

우리는 종종 이러한 인터뷰 질문을 봅니다. String, StringBuilder 및 StringBuffer의 차이점에 대해 간략하게 이야기하십시오. 이 중 String은 다른 두 개와 다르며 일단 String 값이 초기화되면 변경할 수 없으며 수정하면 새로운 클래스가됩니다. 다음 코드를 살펴보면 마지막에 "ssssss"가 출력되지만 String 값이 수정 된 것 같습니다.

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

실제로 Debug를 통해 String 값이 수정되지 않았 음을 직관적으로 알 수 있습니다.
문자열 불변성
문자열 불변성
처음에 str이 가리키는 메모리 주소는 527이고 할당 라운드 후에 str이 가리키는 메모리 주소는 529가됩니다. 즉, str = "ssssss"의 단순 해 보이는 할당은 실제로 str의 참조가 새 문자열을 가리 킵니다.

이제 String의 소스 코드에서 이유를 살펴 보겠습니다.

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

String의 소스 코드에서 볼 수 있습니다.

  1. 문자열은 final에 의해 수정되어 String 클래스가 상속되지 않음을 나타냅니다. 즉, String의 모든 작업 메서드는 상속으로 덮어 쓰여지지 않습니다 .
  2. String에 저장된 데이터는 char 배열 값입니다. 우리는 값이 final에 의해서도 수정된다는 것을 발견했습니다. 즉, 값이 할당되면 메모리 주소는 절대 수정할 수 없으며 값의 권한은 비공개이며 외부에서 절대적으로 액세스 할 수 없으며 String은 값 할당을 열지 않았습니다. 메서드, 따라서 값이 생성되면 메모리 주소를 전혀 수정할 수 없습니다 .

위의 두 가지 사항은 String의 불변성에 대한 이유입니다. final 키워드의 특성을 최대한 활용하고 있습니다. 클래스를 커스터마이즈 할 때 불변이되고 싶다면이 두 가지 String 연산을 모방 할 수도 있습니다.

1.2, 평등 판단

평등을 판단하는 두 가지 방법, equals 및 equalsIgnoreCase가 있습니다. 후자가 동일하다고 판단되면 케이스는 무시됩니다. 두 문자열의 동일성을 판단하는 논리를 작성하라는 요청을 받으면 작성 방법에 따라 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;
}

equals의 소스 코드에서 볼 수 있듯이 논리는 매우 명확하며 동등한 코드는 완전히 String의 기본 구조를 기반으로 작성됩니다. 이것은 또한 우리에게 사고 방식을 제공합니다. 누군가가 둘이 같은지 판단하는 방법을 묻는다면, 우리는 둘의 기본 구조에서 시작할 수 있으므로 기본 문자열처럼 실용적인 아이디어와 방법을 빠르게 생각할 수 있습니다. 데이터 구조는 char 배열과 동일하며 동등성을 판단 할 때 char 배열의 문자를 하나씩 비교하여 동일한 지 확인합니다.

2 : 긴

2.1, 캐시

Long의 캐싱 문제가 가장 우려됩니다. Long은 -128에서 127까지 모든 Long 값을 캐시하는 캐싱 메커니즘을 구현했습니다.이 범위의 Long 값이면 초기화되지 않지만 캐시에서 가져 오면 캐시 초기화 소스 코드는 다음과 같습니다.

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);
    }
}

3 : 인터뷰 질문

3.1. Long을 사용할 때 valueOf 메소드를 더 많이 사용하고 parseLong 메소드를 덜 사용하는 것이 권장되는 이유는 무엇입니까?

Long 자체에는 -128 ~ 127 범위의 Long을 캐시하는 캐싱 메커니즘이 있기 때문에 valueOf 메소드는 캐시에서 값을 가져옵니다. 캐시가 적중되면 리소스 오버 헤드를 줄입니다. parseLong 메소드에는이 메커니즘이 없습니다.

3.2 왜 모든 사람들이 String이 불변이라고 말하는가?

final 키워드에 의해 데이터를 보유하고있는 String과 char 배열이 모두 수정되면 변경이 불가능하므로 자세한 내용은 위를 참조하시기 바랍니다.

3 : 요약

우리 작업에서는 String과 Long이 자주 사용되며, 면접 과정에서 시험관은 실력을 확인하기 위해 몇 가지 실용적인 질문을하는 것을 좋아합니다.

추천

출처blog.csdn.net/weixin_38478780/article/details/107762049