티스토리 뷰
@Override 어노테이션을 일관되게 사용하라
해당 어노테이션을 일관되게 사용하면 여러가지 악명 높은 버그들을 예방해준다.
다음 Bigram 프로그램을 살펴보자. Bigram은 영어 알파벳 2개로 구성된 문자열을 표현하는 소스다.
pubcli class Bigram {
private final char first;
private final char second;
public Bigram(char firtst, 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());
}
}
}
main 메소드에서 보듯이 똑같은 소문자 2개로 구성된 Bigram 26개를 10번 반복 후 집합에 추가하여, 그 집합의 크기를 출력한다.
Set은 중복이 허용되지 않으므로, 26이 출력될 거 같지만 실제로는 260이 출력된다...?!
확실히 Bigram 작성자는 equals 메소드를 재정의 한 것으로 보이고, hashCode도 함께 재정의했다.(아이템10, 11)
그런데 자세히 살펴보면, equals를 overriding한 게 아니라 overloading을 해버린 것이다.
Object의 equals를 재정의하려면 매개변수 타입을 Object로 해야만 하는데 그렇게 하지 않았다. 그로인해, Object에서 상속한 equals와는 별개로 새로운 equals 메소드를 정의한 꼴이 되버린 것이다.
Object의 equals는 == 연산자와 똑같이 객체 식별성만을 확인한다. 따라서 같은 소문자를 소유한 Bigram 10개 각각이 서로 다른 객체로 인식되고 결과적으로 260이라는 결과가 출력된 것이다.
그럼 equals()에 @Override를 달고 다시 컴파일 해보자
@Override
public boolean equals(Bigram b) {
...
}
//결과 : 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를 달자
@Override를 안달아도 되는 예외 케이스
@Override를 안달아도 되는 예외 케이스가 있다.
구현체 클래스에서 상위 클래스의 추상 메소드를 재정의할 때는 굳이 @Override를 달지 않아도 된다.
- 이유는, 구현체 클래스에서 추상 클래스의 추상 메소드를 구현하지 않으면 컴파일러가 그 사실을 바로 알려주기 때문이다.
핵심 정리
재정의한 모든 메소드에 @Override를 의식적으로 달면 우리가 실수했을 때 컴파일러에 의해 알 수 있다.
예외 케이스는 구현체 클래스에서 상위 클래스의 추상 메소드를 구현할 시 @Override를 안 달아도 되나 다는 것도 해로울 것은 없다.
즉, 재정의를 할 시에는 @Override를 다는 것이 가독성도 좋고 안전성도 높다.
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 아이템 10. equals는 일반 규약을 지켜 재정의하라 (0) | 2020.02.08 |
---|---|
[ Effective Java] 아이템 39. 명명 패턴보다 어노테이션을 사용하라 (0) | 2020.02.07 |
[Effective Java] 아이템 70. 복구할 수 있는 상황에는 검사 예외, 프로그래밍 오류에는 런타임 예외를 사용하라 (0) | 2020.02.06 |
[Effective Java] 아이템 69. 예외는 진짜 예외 상황에서만 사용하라 (0) | 2020.02.06 |
[Effective Java] 아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용해라 (0) | 2020.02.03 |
- Total
- Today
- Yesterday
- java
- 팩토리 메소드 패턴
- 빈 순환 참조
- 점층적 생성 패턴
- 연관관계
- 이펙티브자바
- 빌더 패턴
- 김영한
- 복사 팩토리
- ifPresent
- 인프런
- @Lazy
- 스프링부트
- Effective Java
- try catch finally
- Spring
- 이펙티브 자바
- springboot
- 자바8
- effectivejava
- JPA
- jdk버전
- package-private
- flatMap
- try with resources
- mustache
- 생성자
- junit
- java8
- 정적팩터리메서드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |