Skip to content

String이 hashCode()를 오버라이딩한 이유 #2

Description

@beginin15

image

  1. A1.hashCode()와 A2.hashCode()의 값은 같을까 다를까?
  2. A1 == A2의 결과는 true일까 false일까?
  3. A1.equals(A2)의 결과는 true일까 false일까?

Q. 여기서 1번의 결과는 같다. 이유는 String이 hashCode()를 재정의 했기 때문. 왜 재정의 되어있는가?

Activity

  1. changed the title [-]String이 hashcode 메소드를 오버라이딩한 이유[/-] [+]String이 hashCode()를 오버라이딩한 이유[/+] on Aug 8, 2021
  2. suhyunsim commented on Aug 9, 2021

    @suhyunsim
    Member

    개발하면서 String을 HashXXX의 Key로 사용하는 경우가 많다.
    만약 hashCode가 오버라이딩 되어있지 않다면? 다음과 같은 상황이 발생한다.

    1. 같은 문자열도 다른 key로 인식되어 저장됨, get으로 값을 얻어올 때 같은 문자열이더라도 key가 다름
    2. 모든 프로젝트에서 String을 상속하는 새로운 클래스를 만들고 hasCode를 오버라이딩해서 사용해야 함
    • 참고: 논리적 동등 비교시 hashCode()를 오버라이딩 해야한는데 Collection 프레임워크에 HashSet, HashMap, HashTable은 아래와 같은 방법으로 동등비교를 한다.
    1. 먼저 hashCode() 값을 비교
    2. equals()로 동등 비교
    3. 위에 과정이 true면 동등한 객체이다.
  3. suhyunsim commented on Aug 9, 2021

    @suhyunsim
    Member

    참고할 주제: 동등성과 동일성

  4. beginin15 commented on Aug 9, 2021

    @beginin15
    MemberAuthor

    질문의 의도는 객체의 동등성 비교를 설명하기 위한 것이고 ‘String’을 예시로 들으신건가 보네요!

    우리가 클래스를 작성할 때 항상 ‘equals()’랑 ‘hashCode()’를 함께 재정의하는 이유랑 동일한 맥락인 것 같아요.

    저는 ‘String’만의 특성이 따로 있는건가 싶어서 이것저것 찾아봤는데 질문의 의도에서 벗어난 것 같긴 하지만 겸사겸사 JVM의 상수풀에 대해서도 공부해보면 좋을 것 같다는 생각이 들었어요.ㅎㅎ

  5. suhyunsim commented on Aug 10, 2021

    @suhyunsim
    Member

    제이의 얘기를 참고해서 지난 번에 정리한 constant pool 내용도 살짝 가져왔어요!

    Constant Pool

    String 객체를 생성하는 방법

    Literal ("")

    • 내용이 같다면 같은 객체
    @DisplayName("literal로 생성 시 동일")
    @Test
    void stringLiteral() {
        String str1 = "abcde";
        String str2 = "abcde";
        assertThat(str1).isEqualTo(str2);
    }

    new 연산자 사용

    • 내용이 같아도 개별적인 객체
    @DisplayName("new로 생성한 String 객체는 값이 같아도 동일하지 않음")
    @Test
    void stringNew() {
        String str1 = new String("1234");
        String str2 = new String("1234");
        assertThat(str1).isNotSameAs(str2);
    }
    • intern() 메서드로 String Pool에 있으면 그 객체를 그대로 리턴, 그렇지 않으면 String Pool에 추가하고 객체의 reference를 리턴
    @DisplayName("String Pool 바깥에 있던 String 객체를 intern -> String Pool에 추가")
    @Test
    void internedString() {
        String constant = "interned String";
        String newString = new String("interned String");
        assertThat(constant).isNotSameAs(newString);
    
        String internedString = newString.intern();
        assertThat(constant).isSameAs(internedString);
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    JavaJava 관련 주제

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions