본문 바로가기

Reading/Effective Java

[Effective-Java] Item 40. @Override 애노테이션을 일관되게 사용하라

@Override


이 애노테이션이 달렸다는 것은 메소드 선언에만 달 수 있으며, 상위 타입의 메소드를 재정의했음을 뜻한다.

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

예외를 두자면 구체 클래스에서 상위 클래스의 추상 메소드를 재정의 할 때는 굳이 @Override를 달 필요는 없다.

구체 클래스인데 아직 구현하지 않은 추상 메소드가 남았다면 컴파일러가 알려주기 때문이다.

내 견해는 다 붙히기로 마음먹었다면 일괄적으로 붙혀두는게 좋을 것 같다.

 

 

일관되게 @Override 애노테이션을 사용하면 두 가지 좋은 점이 있다.

1.  실수로 다중정의(Overloding)해버리는 상황을 막을 수 있다.

2. 컴파일러가 재정의하려는 메소드와 다르거나 그런 메소드가 없는 경우 컴파일 오류를 발생시켜준다.

 

//두 개의 char를 저장
public class Bigram {
    private final char first;
    private final char second;

    public Bigram(char first, char second) {
        this.first  = first;
        this.second = second;
    }
    
    //다중정의한 equals
    public boolean equals(Bigram b) {
        return b.first == first && b.second == second;
    }
    
    //올바르게 Override한 equals
    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Bigram))
            return false;
        Bigram b = (Bigram) o;
        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());
    }
}

 

메인문을 보면 (a,a)~(z,z) 즉 26개의 Bigram을 10번 저장했고, HashSet을 사용한 것을 보아 중복이 허용되지 않으니

26의 출력을 기대했을 것이다. 하지만 위 코드는 equals를 정의는 했지만 Overriding하지 않았다.

그리고 Objects의 equals를 재정의 하려면 매개변수 타입을 Object로 해야만 하는데, 지켜지지 않았기 때문에 다중정의된 것이다.

 

따라서 Bigram의 equals는 Object의 equals를 HashSet에 추가할 때 사용하고 ==연산자로 식별성만 확인하여 260을 출력한다.

@Override 애노테이션을 붙혔다면 컴파일 시점에서 오류를 알아차릴 수 있었다.

 

 

클래스뿐 아니라 인터페이스의 메소드를 재정의 할때도 사용하자

자바8부터 디폴트 메소드를 지원하며, interface메소드를 구현한 메소드에도 애노테이션을 달면 시그니처가 올바른지 확신할 수 있다.

그리고 추상 클래스나 인터페이스에서도 상위 클래스나 상위 인터페이스의 메소드를 재정의하는 모든 메소드에 @Override를 다는게 좋다.

상위 클래스가 구체 클래스든 추상 클래스든 마찬가지다.

 

예를들어 Set 인터페이스는 Collection 인터페이스를 확장했지만 새로 추가한 메소드는 없다.

따라서 모든 메소드 선언에 @Override를 달아 실수로 추가한 메소드가 없음을 보장했다.

 

 

 

기타 추가사항


IDE들은 관련설정을 활성화 해두면  @Override가 달리지 않은 메소드가 실제로는 재정의 했다면 경고를 주게할 수 있다.

컴파일 오류의 보완재 역할이다. Intellij MAC기준으로 preferences - Editor - Inspections 에서 아래문항을 체크하면 된다.

 

 

 

 

* 위 글은 EffectiveJava 3/E 책 내용을 정리한 글로, 저작권 관련 문제가 있다면 댓글로 남겨주시면 즉각 삭제조치 하겠습니다.