Java/Effective Java

[Effective Java] 아이템 40. @Override 어노테이션을 일관되게 사용하라

메성 2020. 2. 6. 01:40
반응형

@Override 어노테이션을 일관되게 사용하라

해당 어노테이션을 일관되게 사용하면 여러가지 악명 높은 버그들을 예방해준다.

다음 Bigram 프로그램을 살펴보자. Bigram은 영어 알파벳 2개로 구성된 문자열을 표현하는 소스다.

pubcli class Bigram {
  private final char first;
  private final char second;

  public Bigram(char firtst, char second) {
    this.first = first;
    this.second = second;
  }
  public boolean equals(Bigram b) {
    return b.first == first && b.second = second;
  }
  public int hashCode() {
    return 31 * first + second;
  }
  public static void main(String [] args) {
    Set<Bigram> s = new HashSet<>();
    for(int i = 0; i < 10; i++) {
      for(char ch = 'a'; ch <= 'z'; ch++) {
          s.add(new Bigram(ch, ch));  
      }
      System.out.println(s.size());
    }
  }
}

main 메소드에서 보듯이 똑같은 소문자 2개로 구성된 Bigram 26개를 10번 반복 후 집합에 추가하여, 그 집합의 크기를 출력한다.

Set은 중복이 허용되지 않으므로, 26이 출력될 거 같지만 실제로는 260이 출력된다...?!

 

확실히 Bigram 작성자는 equals 메소드를 재정의 한 것으로 보이고, hashCode도 함께 재정의했다.(아이템10, 11)

 

그런데 자세히 살펴보면, equals를 overriding한 게 아니라 overloading을 해버린 것이다.

Object의 equals를 재정의하려면 매개변수 타입을 Object로 해야만 하는데 그렇게 하지 않았다. 그로인해, Object에서 상속한 equals와는 별개로 새로운 equals 메소드를 정의한 꼴이 되버린 것이다.

 

Object의 equals는 == 연산자와 똑같이 객체 식별성만을 확인한다. 따라서 같은 소문자를 소유한 Bigram 10개 각각이 서로 다른 객체로 인식되고 결과적으로 260이라는 결과가 출력된 것이다.

 

그럼 equals()에 @Override를 달고 다시 컴파일 해보자

@Override 
public boolean equals(Bigram b) {
  ...
}
//결과 : method does not override or implement a method from a supertype.

//수정해보자
@Override 
public boolean equals(Object o) {
  if(!(o instanceof Bigram)) {
    return false;
  }
  Bigram b = (Bigram) o;
  return b.first == first && b.second == second;
}

그러니 상위 클래스의 메서드를 재정의하려는 모든 메서드에는 @Override를 달자

 

 

@Override를 안달아도 되는 예외 케이스

@Override를 안달아도 되는 예외 케이스가 있다.

구현체 클래스에서 상위 클래스의 추상 메소드를 재정의할 때는 굳이 @Override를 달지 않아도 된다.

  • 이유는, 구현체 클래스에서 추상 클래스의 추상 메소드를 구현하지 않으면 컴파일러가 그 사실을 바로 알려주기 때문이다.

 

핵심 정리

재정의한 모든 메소드에 @Override를 의식적으로 달면 우리가 실수했을 때 컴파일러에 의해 알 수 있다.

예외 케이스는 구현체 클래스에서 상위 클래스의 추상 메소드를 구현할 시 @Override를 안 달아도 되나 다는 것도 해로울 것은 없다.

즉, 재정의를 할 시에는 @Override를 다는 것이 가독성도 좋고 안전성도 높다.

반응형