Skip to content

Latest commit

 

History

History
78 lines (62 loc) · 9.57 KB

10.equals 만들 때 일반규약을 지켜라 귀찮으면 IDE가 만들어주는거 써라.md

File metadata and controls

78 lines (62 loc) · 9.57 KB
  • equals가 뭐야?

    • equals 객체 끼리 내용을 비교할 수 있게 만드는 공통 메서드 ( Object 클래스에 정의되 있음 )
    • == 과의 차이는 ?
      • equals 는 논리적 동치성을 확인할 때 사용. 객체의 내용이 같은지 확인 ( 재정의 시 )
        • 논리적 동치성 : 논리적으로 같은지 확인함 ( 동등성 )
      • == 는 객체 식별성 ( 물리적으로 같은가 , 동일성)를 확인할 때 사용. 주소값이 같은지 확인
    • equals 재정의 하는 이유? 논리적 동치성을 표현하기 위해서!
  • 언제 equals 를 재정의할까?

    • 객체 식별성이 아니라 논리적 동치성을 확인해야 할 때

      Object에 정의된 equals

      Object에 정의된 equals

      • 원래 equals는 재정의하지 않으면 == 비교를 하기 때문에 객체 식별성을 비교하게 됨.
    • 상위 클래스에서 equals가 논리적 동치성을 비교하도록 재정의되지 않았을 때

  • equals 를 정의하지 않는 것이 좋을 때

    • equals 재정의는 자칫 실수할 우려가 있음
      • 잘못 구현해놓으면 당연히 일반 규약들을 지키고 있는 줄 아는 클래스들(List, Set 등)에 영향을 줌 → 어떻게 반응할 지 모름
      • 오히려 잘못 구현하는 것보다 그냥 재정의 안하고 그냥 두는게 가장 최선일 수 있음
    1. 각 인스턴스가 본질적으로 고유할 때
      • 값을 표현하는 객체가 아닌 동작하는 객체를 표현하는 클래스(Like Thread)의 경우
    2. 인스턴스의 논리적 동치성을 검사할 일이 없을 때
    3. 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 맞을 때
    4. 클래스가 private 이거나 package-private 이고 equals 메서드를 호출할 일이 없을 때
  • equals 재정의 할 때 지켜야할 일반 규약

    • equals 는 동치관계를 구현하므로 일반 규약을 만족해야함
    1. 반사성
      • x.equals(x)는 true다. (x 는 not null)
      • 일반적으로 만족시키지 않는게 더 힘듬.
    2. 대칭성
      • x.equals(y)가 true면 y.equals(x)도 true다. (x, y는 not null)

        스크린샷 2022-02-24 00.49.50.png

        • 위는 절대값을 만들어주는 Integer로 equals로 다른 Integer가 들어왔을 때 절댓값으로 변경하여 비교하는 방식으로 equlas를 재정의 했다.

        스크린샷 2022-02-24 00.51.30.png

        • 대칭성을 위반하게 된다.
    3. 추이성
      • x.equals(y)가 true이고 y.equals(z)도 true이면 x.equals(z)도 true이다 (x, y, z는 not null)

      • 상위 클래스에 없는 새 필드를 하위클래스에 추가할 때 자주 발생한다.

        스크린샷 2022-02-24 01.20.16.png

        스크린샷 2022-02-24 01.20.26.png

        • ColorPoint는 Point에서 Color가 추가된 클래스다.

        스크린샷 2022-02-24 01.20.01.png

        • 추이성을 위반하게 된다.
    4. 일관성
      • x.equals(y)를 반복해서 호출하면 항상 true or 항상 false를 반환한다. (x, y는 not null)
      • 가변 객체는 비교 시점에 따라 서로 다를 수도 같을 수 있다. 하지만 불변 객체는 한번 다르면 끝까지 달라야 한다.
    5. null-아님
      • x.equals(null)은 false이다. (x는 not null)
      • 모든 객체가 null과 같지 않아야 한다
        • 보통 equals 내부에서 명시적으로 if (o == null) 로 할 필요 없다.
        • 묵시적으로 if (!(o instanceof MyType) 이런 식으로 비교해서 처리하면 null도 한번에 처리된다.
  • 양질의 equals 메서드 구현 방법

    1. == 연산자 이용해서 자기 자신의 참조인지 확인
    2. instanceof 연산자 이용해서 입력이 올바른 타입인지 확인
    3. 입력을 올바른 타입으로 형변환 ( 2번이 되면 100% 성공 )
    4. 입력 객체와 자기 자신의 대응되는 핵심 필드들이 모두 일치하는지 하나씩 검사
    5. equals를 다 구현했다면 대칭적인가? 추이성이 있는가? 일관적인가 확인
      • 사실 반사성, null-아님은 문제되는 경우가 거의 없음
    6. equals를 재정의 할 때 hashCode도 반드시 재정의하자
    7. 너무 복잡하게 해결하려 들지마라
    8. Object 외의 타입을 매개변수로 받는 equals 메서드는 선언하지 마라
    • AutoValue 프레임워크나 IDE에서 제공해주는 것이 사람이 직접 작성하는 것보다 나을 때가 많다.

🔥 꼭 필요한 경우 아니면 equals를 재정의하지 마라! 그래도 굳이 재정의하려면 핵심 필드를 모두 빠짐없이, 다섯 가지 규약을 모두 지켜가며 비교해라