티스토리 뷰

오버라이딩과 오버로딩의 차이를 말씀해 주세요~

신입 개발자 면접 질문 목록에 단골로 등장하는 질문이다. (근데 이거 진짜 물어보나?..)

위 질문에 답할 수 있다면 매우 쉬운 내용이다.

 

 

 

아래의 소스 코드에서 버그를 찾아보자

import java.util.*;

// 코드 40-1 영어 알파벳 2개로 구성된 문자열(바이그램)을 표현하는 클래스 - 버그를 찾아보자. (246쪽)
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());
    }
}

일단 본인은 못 찾았다. 책 읽고 알았다.

main문에서 표현하고 싶은 것은 'a', 'a'부터 'z', 'z'까지의 객체를 중복해서 10번 집어넣는다. Object의 hashCode와 equals를 재정의 하여 중복을 허용하지 않는 HashSet의 size가 26가 나올 것으로 예상된다. 그러나 실제 결과는 260을 반환한다. 문제는 equals method에 있다.

Object의 equals이다. 아뿔싸 parmeter type이 Object이다. 상위 객체의 method를 Overriding(재정의)하기 위해선 method의 시그니처(method 이름, 파라미터 타입, 파라미터 순서)가 일치해야 한다. method의 이름만 같고 파라미터가 다른 경우Overloading(다중 정의)가 된다. HashSet은 객체의 유일성 체크를 Object의 equals와 hashCode를 통해 하게 되는데 재정의 했다고 믿었던 equals가 사실은 reference를 비교하는 Object의 method가 그대로 실행된 것이다.

 

 

이런 실수를 방지하기 위해 @Override를 사용할 수 있다.

// 컴파일 에러
@Override
public boolean equals(Bigram b) {
    return b.first == first && b.second == second;
}

// 성공!
@Override public boolean equals(Object o) {
    if (!(o instanceof Bigram))
        return false;
    Bigram b = (Bigram) o;
    return b.first == first && b.second == second;
}

@Override를 달아 명시적으로 재정의 된 method임을 표시한다. 위의 코드는 컴파일 에러를 발생시킨다. 상위 객체에 똑같이 생긴 method가 없기 때문이다. 아래와 코드와 같이 수정하면 발생했던 버그가 해결된다.

 

 

 

@Override를 안 달아도 되는 경우는 abstract class나 interface를 확장한 경우이다. 얘네는 method 구현을 안 하면 컴파일 타임에 에러가 난다. 그러나 지난 아이템에서 어노테이션은 마킹의 의미로 단다고 했으니 명시적으로 재정의 됐음을 보여주는 것이 읽기에도 좋다. -> IDE에서 method를 생성하면 자동으로 붙여준다. IDE의 기능을 활용하자.

 

 

 

 

// 추가

그렇다면 @Override를 처리하는 코드는 어디 있을까? 이것도 lombok처럼 미리 정의된 annotation processor가 존재하는지 궁금해졌다. 나랑 똑같은 생각을 한 외국인 분이 질문을 했다.

https://stackoverflow.com/questions/31097555/how-to-implement-something-similar-to-the-override-java-annotation

 

How to implement something similar to the @Override java annotation?

With this jdk code in ../java/lang/Override.java, package java.lang; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }

stackoverflow.com

 

요약하면 javac.java.lang 패키지의 어노테이션들은 따로 정의된 annotation processor가 있는 것이 아니라 JAVA 컴파일러에서 처리한다고 한다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/09   »
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
글 보관함