package java.lang;
import java.lang.annotation.*;
/**
* Indicates that a method declaration is intended to override a
* method declaration in a supertype. If a method is annotated with
* this annotation type compilers are required to generate an error
* message unless at least one of the following conditions hold:
*
* <ul><li>
* The method does override or implement a method declared in a
* supertype.
* </li><li>
* The method has a signature that is override-equivalent to that of
* any public method declared in {@linkplain Object}.
* </li></ul>
*
* @author Peter von der Ahé
* @author Joshua Bloch
* @jls 8.4.8 Inheritance, Overriding, and Hiding
* @jls 9.4.1 Inheritance and Overriding
* @jls 9.6.4.4 @Override
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Target(ElementType.METHOD) : 메서드 선언에만 달 수 있음
@Retention(RetentionPolicy.SOURCE) : 소스코드(.java)까지 유지
@Override 어노테이션은 상위 타입의 메서드를 재정의할때 사용한다. @Override를 일관되게 사용하면, 여러가지 버그를 예방할 수 있다.
다음은 Object.equals와 Object.hashCode를 재정의한 클래스 코드이다.
public class Biagram {
private final char first;
private final char second;
public Biagram(char first, char second) {
this.first = first;
this.second = second;
}
public boolean equals(Biagram b) {
return b.first == first && b.second == second;
}
public int hashCode() {
return 31 * first + second;
}
public static void main(String[] args) {
Set<Biagram> s = new HashSet<>();
for (int i = 0; i < 10; i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
s.add(new Biagram(ch, ch));
}
}
System.out.println(s.size()); // 260
}
}
여기서 Set은 중복을 허용하지 않으므로 s.size는 26이 출력될거라 예상하지만, 260이 출력된다. 그 이유는 equals 메서드를 재정의한 것이 아닌 다중정의(overloading)을 했기 때문이다. 이러한 오류를 컴파일러가 찾아내게 하려면 @Override 어노테이션을 추가해 Object.equals 를 재정의하려는 의도를 명확하게 나타내야한다.
public class Biagram {
private final char first;
private final char second;
public Biagram(char first, char second) {
this.first = first;
this.second = second;
}
@Override public boolean equals(Biagram b) {
return b.first == first && b.second == second;
}
@Override public int hashCode() {
return 31 * first + second;
}
public static void main(String[] args) {
Set<Biagram> s = new HashSet<>();
for (int i = 0; i < 10; i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
s.add(new Biagram(ch, ch));
}
}
System.out.println(s.size());
}
}
java: method does not override or implement a method from a supertype
@Override를 붙이게되면 컴파일러는 해당 메서드가 상위 메서드와 다르다는 것을 찾아 오류가 발생하며, 올바르게 수정할 수 있다.
즉, 상위 클래스의 메서드를 재정의하는 모든 메서드에 @Override 어노테이션을 다는것을 권장한다. 단, 상위 클래스의 추성 메서드는 굳이 @Override를 달지 않아도 된다.
@Override 어노테이션을 정리하자면 다음과 같다.
클래스, 인터페이스의 메서드를 재정의할 때 사용
시그니처가 올바른지 재차 확인 가능
컴파일타임에 오류 발견 가능
추상 클래스나 인터페이스에서는 상위 클래스, 상위 인터페이스의 메서드를 재정의한 모든 메서드에 추가하는 것을 권장