String vs Object

노지환·2021년 12월 4일
0

String 클래스

문자열을 저장하기 위해서 char[] value를 인스턴스 변수로 정의하고 있는 클래스

한번 생성된 String은 변경할 수 없다!
-> +연산자를 이용해 문자열을 결합하는 경우 새로운 문자열이 담긴 인스턴스가 생성된다!
-> 따라서, 문자열을 다루는 작업이 필요한 경우StringBuffer클래스를 사용하자!

String을 만들 때 사용하는 두가지 방법

String literal = "abc";
String constr = new String("abc");

리터럴 지정: 같은 내용의 문자열을 모두 하나의 String인스턴스를 참조.
생성자: new를 통한 메모리 할당으로, 새로운 String 인스턴스 생성

intern() 메서드

String인스턴스의 문자열을 'constant pool'에 등록하는 메서드
이미 등록되어 있다면 문자열의 주소값을 반환함

intern()을 사용하면, equals 대신 ==를 사용할 수 있다.
-> 문자열의 개수가 많은 경우에는 equals보다 성능이 좋다!

Object와 String 비교

String이 Object에서 상속받은 equals와 hashCode를 Object와 비교하며 보려고 한다.

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (!COMPACT_STRINGS || this.coder == aString.coder) {
                return StringLatin1.equals(value, aString.value);
            }
        }
        return false;
}

// StringLatin1의 equals
@HotSpotIntrinsicCandidate
    public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            for (int i = 0; i < value.length; i++) {
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
}

Object를 상속받은 String 클래스는 equals()를 오버라이딩했다.

  • Object와는 다르게, String이 가지고 있는 "값"이 같은지 확인한다.
  • 코드 자체로 서로의 문자들을 일일히 비교하며 작동하기 때문에 이해가 되었다.

궁금한 점은

  1. 리터럴로 String이 생성될 때 constant pool에 등록하는 과정을 찾아볼 수 없었다.
  2. equals를 사용할 때 hashCode역시 오버라이딩을 해야한다고 하는데, 둘의 접점이 String 클래스에서는 찾을 수 없었다.
    -> 해쉬에 대한 추가 공부

equals를 사용할 때는 hashCode역시 오버라이딩해야한다?

따라서, hashCode를 오버라이딩하지 않는다면, 새로운 객체를 만들 때 마다 Object클래스에 정의된 대로 모든 객체가 서로 다른 해시코드를 가질 것이다.
-> 그렇기때문에 equals를 오버라이딩할 때 hashCode메서드도 같이 오버라이딩해야한다?

//String
public int hashCode() {
        int h = hash;
        if (h == 0 && !hashIsZero) {
            h = isLatin1() ? StringLatin1.hashCode(value)
                           : StringUTF16.hashCode(value);
            if (h == 0) {
                hashIsZero = true;
            } else {
                hash = h;
            }
        }
        return h;
}

//StringLatin1.java
public static int hashCode(byte[] value) {
        int h = 0;
        for (byte v : value) {
            h = 31 * h + (v & 0xff);
        }
        return h;
}

가지고 있는 문자(value)를 hash해서 갖는다.
만약에 존재하지 않는다면 새로운 hash값이 생길테고, hash값이 존재한다면 그 존재하는 값을 가지게 된다.

하지만, String 코드에서 hash가 어떻게 사용하는지를 모르겠다.
내가 생각한 가정은,
이 고유한 해쉬가 constant pool에 존재하고, 같은 이름이 들어왔을 때 같은 해쉬값이 나오면, 그 해쉬 값을 기준으로 메모리를 찾아가 연결한다고 생각하였는데 이걸 증명할 수 있을만한 코드가 보이지 않는다.

  1. 리터럴로 만들어지는 String 코드를 알아내야함.
profile
기초가 단단한 프로그래머 -ing

0개의 댓글