기록하기

String Constant Pool 과 equals, hashCode 본문

language/java

String Constant Pool 과 equals, hashCode

jjungdev 2023. 9. 7. 23:13

String Constant Pool

String 클래스는 equals() 메소드를 사용해서 비교를 해야하는데 이는 자바의 Constant Pool 이 존재하기 때문이다.

Constant Pool 이란, 객체 재사용을 하기 위해 만들어진 것으로 String 의 경우 동일한 값을 갖는 객체가 있으면 이 객체를 재사용한다.

즉, Constant Pool 이라는 메모리 공간에 중복되지 않는 String 문자열을 저장하고, 해당 문자열에 접근할 때마다 메모리 주소를 반환하는데 이를 통해 메모리 공간을 절약할 수 있다.

 

그렇다면, 아래의 경우에는 과연 결과가 어떻게 나와야할까?

String test1 = "abc";
String test2 = new String("abc");

//1)
System.out.println(test1 == test2);

//2)
System.out.println(test1.equals(test2));

 

위에서 작성한 내용에 의하면, test1, test2 모두 출력 결과가 abc 이기 때문에 동일한 값을 가지고 있으니 1, 2번 모두 다 true 이지 않을까하는 생각이 들었다.

 

하지만 실제 결과를 출력해보면, 

  • 1) false
  • 2) true

이렇게 결과가 나온다. 왜 그런 것일까?

 

 

먼저, 2)번 equals 비교를 하게 되면 문자열을 비교하기 때문에 true 가 나오는 것을 쉽게 이해할 수 있다.

하지만 1)번의 경우에는 == 비교 자체가 주소값을 비교하는 것인데 test1, test2 주소가 다르기 때문에 false 라는 결과가 나온 것이다.

 

그렇다면 또 왜 주소가 다를까? Constant Pool 에서 가져올 수 있는 것이 아닌가?

이는 바로 new String() 으로 객체를 생성해서 이다. 이렇게 객체를 생성하면 같은 값의 객체를 생성하더라도 Constant Pool 에서 재사용하지 않고, 별도의 객체를 생성하기 때문에 이 둘의 메모리 번지가 다른 것이다.

 

그렇기 때문에 클래스 생성 시 equals, hashCode 메소드 재정의가 필요하다. 즉 내가 원하는대로 동작하지 않을 수 있기 때문에 이를 방지하고자 재정의가 필요하다.

 

이펙티브 자바의 내용을 참고하여 equals 재정의 규칙만 정리해보자

 

 

equals 재정의 규칙

equals 재정의 규칙은 다음과 같다.

  1. == 연산자를 사용해 자기 자신의 참조인지 확인한다. -> 자기 자신이면 true
  2. instanceof 연산자로 입력이 올바른 타입인지 확인한다.
  3. 입력을 올바른 타입으로 형변환한다.
  4. 핵심 필드들이 모두 일치하는지 확인한다.

 

항상 lombok 을 활용했었는데, 곧 만들어 볼 프로젝트에는 lombok 의존성을 모두 제거하고 Model 객체에 equals, hashCode, toString, serializable 을 구현해볼 생각이다.

 

'language > java' 카테고리의 다른 글

try-with-resources 사용법 예시와 AutoCloseable 구현  (0) 2023.09.16
Java의 GC 진행 방법  (0) 2023.08.18
List, Set, Map 의 차이  (0) 2022.06.11