@Override 애노테이션을 제대로 사용하기
•
메서드에 @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 b) {
return b.first == first && b.second=second;
}
public int hashCode() {
return 31 * first + second;
}
public static void main(String[] arqs) {
Set<Biqram> 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());
}
}
Java
복사
•
위 코드는 똑같은 소문자 2개로 구성된 Bigram 26개를 10번 반복해 Set에 추가하고 그 집합의 크기를 출력하는 코드이다. 의도한 동작은 Set에서 중복을 허용하지 않기 때문에, 26이 출력되기를 기대하지만 실제 260이 출력된다.
•
그 이유는 equals 메서드를 재정의(overriding) 한 것이 아니라 다중정의(overloading) 했기 때문이다. equals는 Object의 메서드로 매개변수를 Object 타입을 받는데, Bigram을 매개변수로 받기 때문에 다중정의가 되버렸다.
@Override public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
Java
복사
•
단순히 이와 같이 @Override 애노테이션을 붙인다고 해결되지는 않지만, 적어도 컴파일타임에 오류를 발생 시켜주고 잘못된 부분을 짚어주기 때문에 오동작을 막아줄 수 있다.
@Override public boolean equals(Object o) {
if (!(o instanceof Bigram)) return false;
Bigram b = (Bigram) o;
return b.first == first && b.second == second;
}
Java
복사
•
이러한 이유로 상위 클래스의 메서드를 재정의하려는 모든 메서드에 @Override 애노테이션을 달자.
•
예외적으로 상위 클래스의 추상 메서드의 경우 구체 클래스가 없다면 컴파일러에서 바로 알려주기 때문에 @Override 애노테이션을 굳이 달지 않아도 된다.
•
클래스를 상속 받는 경우 뿐 아니라 인터페이스를 구현하는 경우에도 @Override를 달아주는 습관을 가지는게 좋다.