-
같은 value 값을 가지는 String들의 hashcode가 같은 이유Java/Basics 2020. 6. 19. 13:31
같은 value 값을 가지는 String들의 hashcode가 같은 이유가 궁금해졌다.
hashcode 대해 공부하던 도중 "test"와 new String("test")의 hashcode 값이
당연히 다를 줄 알았다. 왜냐하면 hashcode는 객체의 16진수 주소값을 10진수화
한 것이기 때문이다. "test"와 new String("test")는 저장되는 영역이 다르기 때문에 주소값도
다를 것이고 이에 따라 hashcode의 값도 달라야 한다는게 내 생각이었다.
하지만 결론부터 말하자면, 주소값은 다르지만 hashcode는 같았다. 왜 그럴까?
■hashcode 간단 설명 (String에서의 hashcode를 설명하기 위한 빌드업)
어떤 인스턴스는 주민등록번호와 같은 고유한 값을 가지고 있다.
그것이 바로 16진수로 표현된 주소값이다.
이 16진수 주소값을 10진수로 변환시킨 것이 hashcode이다.
hashcode는 인스턴스마다의 고유한 값이라는 특징 때문에
다수의 객체를 다루는 JCF에서 많이 사용된다.
(왜 16진수를 그대로 사용하지 않고 변환시켜 하는지는 잘 모르겠다)
■JCF에서의 String
그렇다면 String이 JCF의 HashMap에서 사용될 때를 생각해보자.
- hashMap.put("test", new FirstObject());
- hashMap.put(new String("test"), new SecondObject());
두 경우가 있다.
if ("test"와 new String("test")의 hashcode가 같다면) {
hashMap 내의 "test"에 대한 value는 FirstObject -> SecondObject로 교체된다.
} else if ("test"와 new String("test")의 hashcode가 다르다면) {
hashMap 내에 (사용자 입장에서 봤을 때) "test"라는 key로
FirstObject, SecondObject 두 value가 저장된다.
}
String 설계자(?)는 else if의 경우 사용자에게 혼란을 일으킬 수 있다고 본 것같다.
그래서 리터럴 형식과 생성자 형식의 String들을 어느정도 동일하게 취급해야할
필요성을 느꼈을 것 같다. 이건 직접 얘기를 들어본 것이 아니라서 추측이다!!!
문득 String 생성자를 한번 열어보고 싶어졌다.
아래는 일반적으로 가장 많이 사용하는 String 생성자이다.
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}new String("test")의 경우 "test"가 이미 생성된 상태이고, 이미 생성된
"test"를 String형식으로 받아 그 hash 값과 value를 참조하여 생성된다.
(리터럴 "test"가 String 타입으로 어떻게 변환되는지 궁금하다.
변환될 때 리터럴의 hashCode() 결과값이 hash 필드로 들어갈테니)
그리고 String의 hashCode 메소드는 아래와 같다.
public int hashCode() {
int h = hash;
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;
}초기화 될 때의 hash코드를 그대로 반환한다. 즉, 초기화 될 때 리터럴의 hashCode() 값을
미리 저장시켜 놓은 후 그 값을 계속 사용한다.
■hashcode를 재정의할 때 주의할 점
hashcode를 재정의 할 때에는 equals 메소드도 함께 재정의해야 부작용이 없다.
HashMap에서 key값을 판단할 때, hashcode와 equals 메소드의 반환 값이
같아야 key가 unique하다고 판단하기 때문이다.
만약 String 클래스가 hashcode만 재정의되었다고 한다면
"test"와 new String("test") 가 모두 key값으로 등록될 수가 있다.
의도한 key unique에 도달하지 못한 것이다.
https://jeong-pro.tistory.com/172
https://www.javaguides.net/2018/07/guide-to-java-string-constant-pool.html
'Java > Basics' 카테고리의 다른 글
와일드카드 ? vs 정규 타입 매개변수 T (0) 2020.07.22 Java Thread(with Multi Thread) (0) 2020.06.21 메모리 주소만으로 Heap의 인스턴스에 접근할 수 있을까? (2) 2020.06.17 Java Heap Dump (0) 2020.06.15 JVM, JRE, JDK (0) 2020.06.14 댓글