Java String 클래스 소스 코드 분석

Java String 클래스 소스 코드 분석

package java.lang;

코드 블록 1

public final class String
        implements Comparable<String>, CharSequence {

    // 1. 핵심 기본 배열: 문자열 각 문자 저장
    private final char[] value;

    // 2. 해시값 캐시, 기본값 0
    private int hash;

    // 기본 생성자: 빈 문자열 생성
    public String() {
        this.value = new char[0];
    }
    // 문자열 전달 생성자
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

1. 클래스 선언

public final class String
        implements Comparable<String>, CharSequence
  1. public: 공개 클래스, 프로젝트 어디서든 사용 가능
  2. final: 상속 불가, 문자열 기본 구조 변경 방지
  3. Comparable: 비교 기능 제공, a.compareTo(b) 가능
  4. CharSequence: 문자열 시퀀스 규약, 문자 타입에 속함

2. 핵심 멤버 변수

// 1.底层存储内容
private final char[] value;

// 2. 哈希缓存
private int hash;

① private final char[] value · 문자열 실제 데이터 저장 위치 · "abc" 입력 시 내부적으로 ['a','b','c'] 배열로 저장 · final: 배열 주소 변경 불가 → 문자열 불변성의 근원 · private: 외부 접근 차단, 보장됨 ② private int hash · 해시값 저장, 초기값 = 0 · 용도: 한번 계산해 저장해두고 다음엔 바로 사용, 성능 향상

3. 기본 생성자

public String() {
    this.value = new char[0];
}

· 빈 문자열 "" 생성 · 길이가 0인 빈 문자 배열 할당

4. 복사 생성자 (중요)

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
String s = new String("abc");

· 전달된 문자열의 value 배열 직접 재사용 · 데이터 복사 없음, 메모리 절약

코드 블록 2

// 문자열 길이 가져오기
    public int length() {
        return value.length;
    }

    // 빈 문자열 여부 확인
    public boolean isEmpty() {
        return value.length == 0;
    }

    // 인덱스로 단일 문자 가져오기
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

5. length() 메서드

public int length() {
    return value.length;
}

· 문자열 길이 = 내부 문자 배열 길이

· 배열 길이 직접 반환

6. isEmpty() 빈 문자열 확인

public boolean isEmpty() {
    return value.length == 0;
}

· 배열 길이가 0 → 빈 문자열 ""

7. charAt() 인덱스로 문자 가져오기

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

· 인덱스 범위 확인 먼저 수행 · 범위 초과 시 오류 발생 · 정상 범위면 배열 해당 위치 문자 반환

코드 블록 3

// 중요: 문자열 내용 비교
    public boolean equals(Object anObject) {
        // 1. 동일 객체면 true
        if (this == anObject) {
            return true;
        }
        // 2. String 타입 확인
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            // 3. 길이 다르면 false
            if (n == anotherString.value.length) {
                char[] v1 = value;
                char[] v2 = anotherString.value;
                int i = 0;
                // 4. 문자 하나씩 비교
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

    // 중요: 해시값 계산 + 캐싱
    public int hashCode() {
        int h = hash;
        // 계산된 적 없으면(h=0) 계산 시작
        if (h == 0 && value.length > 0) {
            char[] val = value;
            // 계산식: h = 31 * h + 문자 코드
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h; // 계산값 캐싱, 다음엔 바로 사용
        }
        return h;
    }

8. equals() 소스 코드

public boolean equals(Object anObject) {
    // 1. 동일 객체인지 확인(주소 같음)
    if (this == anObject) {
        return true;
    }

    // 2. String 타입인지 확인
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;

        // 3. 길이 다르면 바로 false
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;

            // 4. 문자 하나씩 비교
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

실행 흐름: this == anObject: 주소 같으면 → 바로 true String 타입 아님 → 바로 false 길이 다름 → 바로 false 하나씩 문자 비교 모두 같아야 true 반환 요약: == 주소 비교 equals 내용 비교

9. hashCode() 해시 메서드

public int hashCode() {
    int h = hash;
    // 계산된 적 없으면(h=0)이고 문자열이 비어있지 않으면
    if (h == 0 && value.length > 0) {
        char val[] = value;
        // 해시 계산 공식
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h; // 계산된 값 캐싱
    }
    return h;
}
  1. h = hash로 캐시 읽기

  2. 처음 사용 시 hash=0이므로 계산 진입

  3. 공식: h = 31 * h + 현재 문자 코드

  4. 계산 후 hash에 캐싱 저장

  5. 다음 호출 시 캐시 바로 사용, 재계산 안함

코드 블록 4

// 문자열 일부 추출
    public String substring(int beginIndex) {
        return new String(value, beginIndex, value.length - beginIndex);
    }

    // 문자열 연결
    public String concat(String str) {
        int len = value.length;
        int otherLen = str.length();
        char[] buf = new char[len + otherLen];
        System.arraycopy(value, 0, buf, 0, len);
        System.arraycopy(str.value, 0, buf, len, otherLen);
        return new String(buf);
    }

    // 자기 자신 문자열 반환
    public String toString() {
        return this;
    }
}

10. 문자열 일부 추출 substring()

public String substring(int beginIndex) {
    return new String(value, beginIndex, value.length - beginIndex);
}

new String( char[] 원본배열, int 시작인덱스, int 추출길이 )

· value 현재 문자열의 기본 char[] 원본 문자 배열 · beginIndex 추출 시작 위치(몇 번째 문자부터 자를지) · value.length - beginIndex 전체 길이 - 시작 위치 = 추출할 문자 개수

  1. 원래 문자 배열 value를 직접 수정하지 않음
  2. 대신 새로운 String 객체 생성
  3. 추출된 내용을 새 문자열에 담아 반환

11. 문자열 연결 concat()

public String concat(String str) {
    int len = value.length;           // 원래 문자열 길이
    int otherLen = str.length();      // 연결할 문자열 길이
    
    char[] buf = new char[len + otherLen]; // [새 배열] 생성
    
    System.arraycopy(value, 0, buf, 0, len); // 원본 문자열 복사
    System.arraycopy(str.value, 0, buf, len, otherLen); // 연결 문자열 복사
    
    return new String(buf); // [새 문자열] 반환
}
  1. 총 길이 = 원래 길이 + 연결할 길이 계산
  2. 더 큰 새 문자 배열 생성
  3. 두 문자열 모두 복사
  4. 마지막으로 새 String 객체 생성 반환

12. toString()

String 자체가 문자열이므로 그대로 자기 자신 반환.

태그: java String 자바 문자열 소스코드

7월 31일 11:04에 게시됨