@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[] 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
}
}
왜 size가 260이 출력될까 ?
원래 set은 중복을 허용하지 않으므로 26이 출력되어야 한다.
equals 메서드를 재정의하려 한 것으로 보이고, hashCode 또한 함께 재정의했다. 하지만 여기서는 equals를 ‘재정의(overriding)’한 게 아니라 ‘다중정의(overloading)’했다.
즉, 매개변수의 타입이 Object가 아니기 때문에, overriding이 아닌 overloading이 되어, equlas를 새로 정의한 형태가 되었다. 따라서 == 만 확인했기 때문에 서로 다른 객체로 인식하여, 260을 출력하게 되었다.
여기서 컴파일러가 오류를 찾아내게 하려면, 아래처럼 재정의한다는 의도를 명시해야 한다.
@Override
public boolean equals(Bigram b) {
return b.first == first && b.second == second;
}
// Bigram. java: 10: 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 애너테이션을 달자
예외: 구체 클래스에서 상위 클래스의 추상 클래스를 재정의할 때는 달지 않아도 된다.
✅ 구체 클래스(concrete class)란?
모든 연산에 대한 구현을 가지고 있는 클래스를 의미하며, 추상 클래스가 아닌 클래스를 모두 concrete class라고 한다.
new 키워드로 객체를 생성할 수 있는 클래스이며 클래스의 모든 메서드를 완벽하게 구현한 클래스를 의미한다.
구체 클래스인데 아직 구현하지 않은 추상 메서드가 남아 있다면 컴파일러가 그 사실을 알려준다.
올바른 사용법
IDE에서 관련 설정을 활성화해놓으면 @Override가 달려있지 않은 메서드가 실제로는 재정의를 했다면 경고를 준다.
@Override 는 클래스뿐 아니라 인터페이스의 메서드를 재정의할 때도 사용할 수 있다. (자바에서 인터페이스에서 디폴트 메서드를 지원하기 시작했기 때문에, 디폴트 메서드가 없음을 안다면 override를 생략해 적는 것이 좋다.)
추상 클래스나 인터페이스에서는 상위 클래스나 상위 인터페이스의 메서드를 재정의하는 모든 메서드에 @Override 를 다는 것이 좋다. 예를 들어 Set 인터페이스의 경우 Collection 인터페이스를 확장했지만 새로 추가한 메서드는 없기에 모두 @Override 를 달아 실수로 추가한 메서드가 없음을 보장했다.
🍑 결론
재정의한 모든 메서드에 @Override 애너테이션을 의식적으로 달면 실수했을 때 컴파일러가 바로 알려준다.
구체 클래스에서 상위 클래스의 추상 메서드를 재정의한 경우엔 해당 애너테이션을 달지 않아도 된다.
Chapter : 6. 열거 타입과 애너테이션
Item : 40.
@Override
애너테이션을 일관되게 사용하라Assignee : Lainlnya
🍑 서론
@Override
는 메서드 선언에만 달 수 있으며, 이 애너테이션이 달렸다는 것은 상위 타입의 메서드를 재정의했음을 뜻한다.🍑 본론
@override
를 일관되게 사용하면 여러 가지 버그들을 예방할 수 있다.왜 size가 260이 출력될까 ?
원래 set은 중복을 허용하지 않으므로 26이 출력되어야 한다.
equals 메서드를 재정의하려 한 것으로 보이고, hashCode 또한 함께 재정의했다. 하지만 여기서는 equals를 ‘재정의(overriding)’한 게 아니라 ‘다중정의(overloading)’했다.
👆 자바 공식 문서에 나와있는 equals
즉, 매개변수의 타입이 Object가 아니기 때문에, overriding이 아닌 overloading이 되어, equlas를 새로 정의한 형태가 되었다. 따라서
==
만 확인했기 때문에 서로 다른 객체로 인식하여, 260을 출력하게 되었다.여기서 컴파일러가 오류를 찾아내게 하려면, 아래처럼 재정의한다는 의도를 명시해야 한다.
⭐️ 상위 클래스의 메서드를 재정의하려는 모든 메서드에
@Override
애너테이션을 달자예외: 구체 클래스에서 상위 클래스의 추상 클래스를 재정의할 때는 달지 않아도 된다.
구체 클래스인데 아직 구현하지 않은 추상 메서드가 남아 있다면 컴파일러가 그 사실을 알려준다.
올바른 사용법
@Override
가 달려있지 않은 메서드가 실제로는 재정의를 했다면 경고를 준다.@Override
는 클래스뿐 아니라 인터페이스의 메서드를 재정의할 때도 사용할 수 있다. (자바에서 인터페이스에서 디폴트 메서드를 지원하기 시작했기 때문에, 디폴트 메서드가 없음을 안다면 override를 생략해 적는 것이 좋다.)@Override
를 다는 것이 좋다. 예를 들어 Set 인터페이스의 경우 Collection 인터페이스를 확장했지만 새로 추가한 메서드는 없기에 모두@Override
를 달아 실수로 추가한 메서드가 없음을 보장했다.🍑 결론
재정의한 모든 메서드에
@Override
애너테이션을 의식적으로 달면 실수했을 때 컴파일러가 바로 알려준다.구체 클래스에서 상위 클래스의 추상 메서드를 재정의한 경우엔 해당 애너테이션을 달지 않아도 된다.
Referenced by