1 minute read

@Override 애너테이션

  • 메서드 선언에만 달 수 있다.
  • 상위 타입 메서드를 재정의했음을 명시한다.
  • 일관되게 사용하면 여러가지 버그들을 예방해 줄 수 있다.

public class Bigram {  
    private final char first;  
    private final char second;  
  
    public Bigram(char first, char second) {  
        this.first = first;  
        this.second = second;  
    }  
  
    public boolean equals(Bigram bigram) {  
    // 매개변수 타입이 Object 가 아니어서
    // 다중정의(Overload)가 되었다. (@Override로 검증 필요)
        return bigram.first == this.first &&  
                bigram.second == this.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()); // 260이 출력된다.
    }  
}

위 코드에서는 @Override 애너테이션을 달지 않았고, 프로그래머가 코드 작성시 실수한 부분을 인지하기 어렵다.

Object.equals()를 재정의하려면 매개변수 타입이 Object여야 하는데 그렇게 하지 않았다. 따라서 같은 소문자를 소유한 Bigram 각각이 서로 다른 객체로 인식되어 260을 출력하는 것이다.

이와 같은 오류는 애너테이션을 명시하면 컴파일러 (혹은 IDE) 상에서 확인이 가능하다.

따라서 명시된 오류 메시지에 따라 올바르게 수정한 메서드는 다음과 같다.

@Override  
public boolean equals(Object o) {  
    if(!(o instanceof Bigram)) {  
        return false;  
    }  
    Bigram b = (Bigram) o;  
    return b.first == this.first &&  
            b.second == this.second;  
}

결론

상위 클래스의 메서드를 재정의하려는 모든 메서드에 @Override 애너테이션을 달자.

  • 상위 클래스의 추상 메서드를 재정의하는 경우에는 애너테이션을 사용할 필요가 없으나, 재정의 메서드 모두에 일괄적으로 애너테이션을 사용하는 것이 좋아 보인다면 모든 재정의 메서드에 사용해도 상관없다.
  • IDE에서는 관련 설정을 활성화한다면, 재정의시 @Override를 사용하지 않았을 때 경고 메시지를 출력하기도 한다.

또한, 클래스 뿐만 아니라 인터페이스의 메서드를 재정의할때도 사용이 가능하다.

  • 인터페이스 메서드를 구현한 메서드에도 @Override 애너테이션을 적용하면 올바르게 재정의하였는지 확인이 가능하다.
  • 추상 클래스나 인터페이스에서는 상위 클래스나 상위 인터페이스의 메서드를 재정의하는 모든 메서드에 @Override를 다는 것이 좋다.

Leave a comment