언제 Java의 @Override 어노테이션을 사용합니까?


498

Java @Override어노테이션 사용에 대한 모범 사례는 무엇 이며 그 이유는 무엇입니까?

재정의 된 모든 단일 메소드를 @Override주석 으로 표시하는 것은 과잉 것 같습니다 . @Override를 사용해야 하는 특정 프로그래밍 상황이 @Override있습니까?

답변:


515

두 가지 이점을 위해 방법을 재정의 할 때마다 사용하십시오. 컴파일러 검사를 이용하여 실제로 생각할 때 메소드를 대체하는지 확인하십시오. 이 방법으로, 메소드 이름의 철자가 틀리거나 매개 변수가 올바르게 일치하지 않는 일반적인 실수를하면, 메소드가 실제로 생각하는대로 대체되지 않는다는 경고가 표시됩니다. 둘째, 메소드를 덮어 쓸 때 더 명확하기 때문에 코드를 이해하기 쉽게 만듭니다.

또한 Java 1.6에서는 메소드가 동일한 이점을 위해 인터페이스를 구현할 때 표시하는 데 사용할 수 있습니다. 별도의 주석 ( @Implements) 을 갖는 것이 더 좋을 것이라고 생각 하지만 아무것도 아닌 것보다 낫습니다.


4
"더 이해하기 쉽다"와 같은 행을 따라 IDE는 @Override 어노테이션을 발견하고 편집기에서 대체 메소드에 시각적으로 플래그를 지정합니다.
Bob Cross

47
일부 IDE는 @Override 주석이없는 재정의 된 메소드에 플래그를 지정합니다.
Jay R.

20
다른 장점은 부모 클래스가 변경되면 컴파일러가 자식 클래스도 업데이트했는지 확인하는 것입니다.
David

4
@Jay R .: 맞습니다. 사실, Eclipse는 @Override가없는 경우 자동으로 추가 할 수도 있습니다.
sleske

32
인터페이스에서 오는 메소드에 대한 @Overrides에 대해 문서화되지 않은 1.5에서 1.6으로 변경되어 다른 사람이 여기에 온 경우 bugs.sun.com/bugdatabase/view_bug.do?bug_id=5008260 은 해당 버그로 보입니다. (
Dick

110

필자는 메서드의 의도가 부모 메서드를 재정의하는 것임을 컴파일 타임 알림으로 가장 유용하다고 생각합니다. 예로서:

protected boolean displaySensitiveInformation() {
  return false;
}

기본 클래스의 메소드를 대체하는 위의 메소드와 같은 것을 종종 볼 수 있습니다. 이것은이 클래스의 중요한 구현 세부 사항입니다. 민감한 정보가 표시되는 것을 원하지 않습니다.

이 메소드가 부모 클래스에서 다음과 같이 변경되었다고 가정하십시오.

protected boolean displaySensitiveInformation(Context context) {
  return true;
}

이 변경으로 인해 컴파일 시간 오류나 경고가 발생하지 않지만 서브 클래스의 의도 된 동작이 완전히 변경됩니다.

질문에 대답하려면 : 수퍼 클래스에서 동일한 서명을 가진 메소드가 부족하여 버그를 나타내는 경우 @Override 주석을 사용해야합니다.


46

여기에는 좋은 답변이 많이 있으므로 다른 방법으로 살펴 보겠습니다.

코딩 할 때 과도한 작업이 없습니다. @override를 입력하는 데 비용이 들지 않지만 메소드 이름의 철자가 틀리거나 서명이 약간 잘못되어 있으면 비용이 크게 절감 될 수 있습니다.

다음과 같이 생각하십시오. 여기를 탐색하고이 게시물을 입력 할 때 남은 생애 동안 @override를 입력하는 것보다 훨씬 더 많은 시간을 사용했습니다. 그러나 하나의 오류로 인해 시간을 절약 할 수 있습니다.

Java는 편집 / 컴파일 타임에 실수를하지 않도록하기 위해 할 수있는 모든 것을 수행합니다. 이것은 포괄적 인 테스트 이외의 다른 방법으로는 막을 수없는 모든 종류의 실수를 해결할 수있는 사실상 무료입니다.

사용자가 메소드를 대체하려고 할 때 실제로 수행했는지 확인하기 위해 Java에서 더 나은 메커니즘을 생각해 낼 수 있습니까?

또 다른 깔끔한 효과는 주석을 제공하지 않으면 컴파일 할 때 실수로 부모 메서드를 오버로딩했음을 경고합니다. 의도하지 않은 경우 중요 할 수 있습니다.


3
"코딩 할 때 과도한 작업은 없습니다." 나는 이것에 동의하기 때문에 동적 랭귀지가 너무 잘못되었다는 것을 알 수 있습니다 (유료 작업의 100 %가 루비에 있지만).
Dan Rosenstark

4
+1 : 재정의 실수로 인해 10 개의 버그가 발생했을 수 있습니다.이 중 하나를 찾는 데 걸리는 시간이 모든 재정의 방법마다 @Override를 입력하는 시간을 쉽게 초과했을 것입니다. 또한 @Override가 다소 부담이된다면 상속을 과도하게 사용하고있을 것입니다.
Lawrence Dol

7
하나의 진짜 단점은 달팽이로 코드를 흩 뜨리면 코드를 읽기가 더 어렵다는 것입니다. 아마도 이것은 내 IDE의 결함이지만, 나는 이것을 직접 경험했습니다.
모드를 잘 치료하십시오.

9
@phyzome "달팽이"가 번거 롭다면 댓글이 충분하지 않습니다. 그것들은 메소드 헤더 위에 단 한 줄이어야하며, 적절한 호버 텍스트와 javadoc을 제공하기 위해 대부분의 경우 (몇 줄) 메서드보다 커야합니다. 나는 문제가 달팽이가 아니라 독서 습관이라고 말하는 것 같습니다. 코드의 모든 괄호가 당신을 귀찮게합니까?
Bill K

4
그렇습니다. 코딩에는 무리가 있습니다. 코드를 분명히하는 것을 막는 주석을 작성할 때.
Ants

22

나는 항상 태그를 사용합니다. 내가 할 수있는 작은 실수를 포착하는 간단한 컴파일 타임 플래그입니다.

tostring()대신 같은 것을 잡을 것 입니다toString()

작은 것들이 큰 프로젝트에서 도움이됩니다.


18

사용하여 @Override주석을 일반적인 프로그래밍 실수에 대한 컴파일 타임 보호 역할을합니다. 실제로 수퍼 클래스 메소드를 대체하지 않는 메소드에 주석이 있으면 컴파일 오류가 발생합니다.

이것이 가장 유용한 경우는 기본 클래스에서 다른 매개 변수 목록을 갖도록 메소드를 변경하는 경우입니다. 수퍼 클래스 메소드를 대체하는 데 사용 된 서브 클래스의 메소드는 변경된 메소드 서명으로 인해 더 이상 그렇게하지 않습니다. 복잡한 상속 구조를 다룰 때 때때로 이상하고 예기치 않은 동작이 발생할 수 있습니다. @Override이에 대한 주석 보호.


가장 좋은 답변입니다. 짧고 달다. "safeguard"가 어떻게 작동하는지 설명 할 수 있기를 바랍니다. 아무도 이것을 설명하지 않았습니다.
djangofan

설명하기 간단합니다. 인터페이스, 추상 클래스 또는 서브 클래스를 변경하여 실수를하면 경고 (예 : Eclipse) 또는 @Override가 작동하지 않는다는 컴파일 타임 오류가 발생합니다. 메시지는 변경된 내용에 따라 다르지만 Eclipse (예 :)에서는 문제가 있음을 매우 빨리 알 수 있습니다. 빨간색 지그재그 밑줄이 작은 것을 볼 수 있으며 문제가되는 텍스트 위에 마우스를 놓으면 무엇이 잘못되었는지 알 수 있습니다. 그 좋은 가치를 호출합니다.
이치로 후루사토

14

컴파일러 검사를 이용하려면 항상 재정의 주석을 사용해야합니다. 그러나 Java 컴파일러 1.5는 인터페이스 메소드를 대체 할 때이 주석을 허용하지 않습니다. 클래스 메서드를 재정의하는 데 사용할 수 있습니다 (추상 여부).

Eclipse와 같은 일부 IDE는 Java 1.6 런타임 이상으로 구성되어 있어도 Java 1.5를 준수하고 위에서 설명한대로 @override를 사용할 수 없습니다. 이러한 동작을 피하려면 프로젝트 속성-> Java 컴파일러-> "프로젝트 특정 설정 사용"확인-> "컴파일러 준수 수준"= 6.0 이상을 선택하십시오.

기본이 인터페이스 또는 클래스 인 경우 메소드를 독립적으로 재정의 할 때 마다이 주석을 사용하고 싶습니다.

이벤트 처리기를 재정의하고 아무 일도 일어나지 않는다고 생각할 때 일반적인 오류를 피하는 데 도움이됩니다. 일부 UI 구성 요소에 이벤트 리스너를 추가한다고 가정하십시오.

someUIComponent.addMouseListener(new MouseAdapter(){
  public void mouseEntered() {
     ...do something...
  }
});

위의 코드는 컴파일되고 실행되지만 someUIComponent 내에서 마우스를 이동하면 실제로는 기본 메소드를 재정의하지 않기 때문에 "일부 실행"코드가 실행됩니다 mouseEntered(MouseEvent ev). 새로운 매개 변수없는 메소드를 작성하기 만하면 mouseEntered()됩니다. 해당 코드 대신 @Override주석을 사용한 경우 컴파일 오류가 발생하고 이벤트 핸들러가 실행되지 않는 이유를 생각하는 데 시간을 낭비하지 않았습니다.


8

자바에서 "인터페이스 재정의"와 같은 것이 없기 때문에 인터페이스 구현 에 대한 @Override 가 일치하지 않습니다.

인터페이스 구현 에 대한 @Override 는 실제로 컴파일이 어쨌든 잡을 수없는 버그를 잡지 않기 때문에 쓸모가 없습니다. 구현 자에 대한 재정의가 실제로 무언가를 수행하는 극도로 페치 된 시나리오는 하나뿐입니다. 인터페이스를 구현하고 인터페이스 REMOVES 메서드를 사용하면 컴파일 타임에 사용되지 않은 구현을 제거해야한다는 알림이 표시됩니다. 인터페이스의 새 버전에 NEW 또는 CHANGED 메소드가있는 경우 새 항목을 구현하지 않을 때 어쨌든 컴파일 오류가 발생합니다.

인터페이스 구현 자에 대한 @Override는 1.6에서 허용되어서는 안되며, Eclipse가 기본 동작으로 주석을 자동 삽입하도록 슬프게 선택하면 많은 혼란스러운 소스 파일이 생성됩니다. 1.6 코드를 읽을 때 메소드가 실제로 슈퍼 클래스의 메소드를 대체하거나 인터페이스를 구현하는 경우 @Override 어노테이션에서 볼 수 없습니다.

실제로 수퍼 클래스에서 메소드를 대체 할 때 @Override를 사용하는 것이 좋습니다.


2
이 시점에서 다양한 의견이 있습니다. stackoverflow.com/questions/212614/…를 참조하십시오 .
sleske

8

오버라이드로 의도 된 모든 메소드와 인터페이스 구현으로 의도 된 모든 메소드에 대해 Java를 사용하는 것이 가장 좋습니다.

먼저 컴파일 타임에 " hashcode()"대신 " " 와 같은 철자가 틀립니다 hashCode(). 실제 원인이 코드를 호출하지 않았을 때 메소드의 결과가 코드와 일치하지 않는 이유를 디버그하는 것은 당황 스러울 수 있습니다.

또한 수퍼 클래스가 메소드 서명을 변경하면 이전 서명의 대체는 "분리 된"상태가되어 혼동되는 데드 코드로 남을 수 있습니다. @Override주석들은 새로운 서명과 일치하도록 수정 될 수 있도록 이러한 고아를 식별하는 데 도움이됩니다.


7

자신이 (비 추상적이지 않은) 메서드를 재정의하는 경우가 많으면 디자인을 살펴 보는 것이 좋습니다. 컴파일러가 그렇지 않으면 오류를 포착하지 않을 때 매우 유용합니다. 예를 들어 ThreadLocal에서 initValue ()를 재정의하려고했습니다.

인터페이스 메소드 (1.6 이상 기능)를 구현할 때 @Override를 사용하면 약간 과도하게 보입니다. 일부 메소드가 재정의되고 일부는 그렇지 않은 메소드가 많으면 아마도 디자인이 다시 좋지 않을 것입니다 (아마도 모르는 경우 편집기가 표시됩니다).


2
실제로, 재정의 된 인터페이스 메소드에도 좋습니다. 예를 들어 인터페이스에서 사용되지 않는 오래된 메소드를 제거하는 경우 해당 메소드는 모든 구현 클래스에서도 제거되어야합니다. @override를 사용하는 경우 클래스를 쉽게 찾을 수 있습니다.
Dominik Sandjaja


7

또 다른 방법은 코드를 읽을 때 부모 클래스의 동작을 변경한다는 것을보다 명확하게하는 것입니다. 디버깅에 도움이 될 수 있습니다.

또한 Joshua Block의 책 Effective Java (제 2 판)에서 항목 36은 주석의 이점에 대한 자세한 내용을 제공합니다.


예, 실제로-항목 36 :)
Chris Kimpton

6

인터페이스 메소드를 구현할 때 @Override를 사용하는 것은 절대 의미가 없습니다. 이 경우 컴파일러를 사용하면 이점이 없습니다. 컴파일러는 이미 실수를 잡을 것이므로 불필요한 혼란입니다.


6
@Override인터페이스에서 사용 하면 인터페이스의 메소드가 제거 될 때이를 알 수 있습니다.
Alex B

@Alex : 인터페이스에서 메소드를 제거하는 것은 메소드를 추가하는 것과 같은 주요 변경 사항입니다. 인터페이스가 게시되면 인터페이스를 사용하는 모든 코드를 완전히 제어하지 않으면 효과적으로 잠 깁니다.
Lawrence Dol

6

메소드가 다른 메소드를 대체하거나 메소드가 인터페이스에서 서명을 구현할 때마다.

@Override주석는 사실 재정의 일에서 한 당신을 보장합니다. 주석이 없으면 맞춤법이 틀리거나 매개 변수 유형 및 숫자가 달라질 수 있습니다.


1
Java 1.6에서 인터페이스 구현을 표시하는 데만 사용할 수 있습니다
Dave L.

5

매번 사용합니다. 1 년 안에 코드를 다시 방문했을 때 무슨 일이 일어나고 있는지 빨리 알아 내고 처음 생각했던 것을 잊어 버린 데 사용할 수있는 더 많은 정보입니다.


5

가장 좋은 방법은 항상 그것을 사용하는 것입니다 (또는 IDE가 당신을 대신하도록하십시오)

@Override 유용성은 계층 구조에 대해보고되지 않은 부모 클래스의 변경 사항을 감지하는 것입니다. 그것이 없으면 메소드 서명을 변경하고 @Override를 사용하여 재정의를 변경하는 것을 잊어 버릴 수 있습니다.

그런 종류의 안전망은 항상 가지고 있습니다.


1
따라서 부모 메서드를 변경하고 자식 클래스의 메서드에서 @Override를 사용하지 않으면 컴파일에서 아무 말이나 침묵을 유지합니까? "재정의"를 사용하면 더 많은 정보를 얻을 수 있습니까? 그렇다면 어떻게해야합니까?
djangofan

5

나는 모든 곳에서 사용합니다. 메소드 마킹에 대한 노력의 주제에서 Eclipse가 나를 위해 그렇게하도록했지만 추가 노력이 필요하지 않습니다.

나는 지속적인 리팩토링에 대해 종교적이다. 그래서, 나는 더 매끄럽게하기 위해 모든 작은 것을 사용할 것이다.


5
  • 메소드 선언에서만 사용됩니다.
  • 어노테이션이있는 메소드 선언이 수퍼 타입의 선언을 대체 함을 나타냅니다.

일관되게 사용하면 많은 종류의 사악한 버그로부터 당신을 보호합니다.

이러한 버그를 피하려면 @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<Bigram>();
        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의 연산자 우선 순위 규칙이 무엇인지 모르지만 equals 메서드가 BUUUUUUUUUUUG! 보다 우선 순위가 낮은 (b.first == first) && (b.second == second)경우에도 씁니다 . &&==
pyon

링크에 해당 페이지의 유용한 부분을 다루는 '구독해야합니다'메시지가 표시된다는 것을 알고 있습니까?
Adriano Varoli 광장

@ Adriano : 죄송합니다 친구 !! 무기력합니다! '답변'을 썼을 때 사용할 수있었습니다. 걱정하지 마십시오. 책을 구입하십시오. 그것을 가질 가치가 있습니다!!
jai

5
는 무시하지 않는 방법과 동일 : 원래는 Object::equals이다 boolean equals(Object), 재정의가 동안 equals이다 boolean equals(Bigram)오버라이드 (override)하지 않는 다른 방법 서명을 가지고있는. 에 @Override를 추가하면 equals이 실수를 감지 할 수 있습니다.
Ming-Tang

3

나중에 starUML에서 리버스 엔지니어링을 수행 할 수 없으므로 무시를 사용할 때주의하십시오. uml을 먼저 만드십시오.


2

여기에있는 지혜가 변하고있는 것 같습니다. 오늘 저는 IntelliJ IDEA 9를 설치 했으며 " 누락 된 @Override 검사 "가 이제 추상 메소드뿐만 아니라 인터페이스 메소드도 구현 한다는 사실을 알게 되었습니다 . 고용주의 코드 기반과 내 프로젝트에서 오랫동안 구현 된 추상 메소드에 대해서만 @Override를 사용하는 습관을 가졌습니다. 그러나 습관을 다시 생각하면 두 경우 모두 주석을 사용하는 장점이 분명해집니다. 더 장황하지만 취약한 기본 클래스 로부터 보호합니다. 인터페이스 메서드 이름이 변경되는 파생 된 문제 (C ++ 관련 예제만큼 심각하지는 않음)를 파생 클래스에서 구현할 메서드를 고아 처리합니다.

물론이 시나리오는 대부분 과장법입니다. 파생 클래스는 더 이상 컴파일되지 않으며 이제 이름이 바뀐 인터페이스 메소드의 구현이 결여되어 있으며 오늘날에는 Rename 메소드를 사용할 것입니다. 에는 전체 코드베이스를 처리하기 위해 리팩토링 작업을 입니다.

구현 된 인터페이스 방법을 무시하도록 IDEA의 검사를 구성 할 수 없기 때문에 오늘은 습관과 팀의 코드 검토 기준을 모두 변경합니다.


2

@Override 어노테이션은 개발자가 상위 클래스 또는 인터페이스에서 올바른 메소드를 대체 할 것인지 여부를 확인하는 데 사용됩니다. super의 메소드 이름이 변경되면 컴파일러는 해당 경우를 통지 할 수 있으며, 이는 super 및 서브 클래스와의 일관성을 유지하기위한 것입니다.

BTW, 서브 클래스에서 @Override 주석을 발표하지 않았지만 super의 일부 메소드를 재정의하면 함수가 @Override와 같은 방식으로 작동 할 수 있습니다. 그러나이 방법은 수퍼의 방법이 변경되면 개발자에게 알릴 수 없습니다. 개발자의 목적을 알지 못했기 때문에 super의 방법을 재정의하거나 새로운 방법을 정의합니까?

따라서 다형성을 사용하기 위해 해당 메소드를 재정의하려는 경우 메소드 위에 @Override를 추가하는 것이 좋습니다.


1

메소드가 재정의되는 시점을 식별하기 위해 최대한 많이 사용합니다. 스칼라 프로그래밍 언어를 보면 오버라이드 키워드도 있습니다. 유용하다고 생각합니다.


0

재정의하는 메소드 이름에 잘못된 철자를 사용했을 때 (컴파일러) 잡을 수 있습니다.


0

재정의 주석은 컴파일러를 활용하여 부모 클래스에서 실제로 메서드를 재정의하는지 여부를 확인하는 데 사용됩니다. 메소드 이름의 철자가 틀린 실수, 매개 변수가 올바르게 일치하지 않는 실수 등의 실수를하는 경우에 사용


0

허용 될 때마다 @override를 코딩하는 것이 가장 좋습니다. 코딩에 도움이됩니다. 그러나, ecipse Helios의 경우 SDK 5 또는 6의 경우 구현 된 인터페이스 메소드에 대한 @override 어노테이션이 허용됩니다. 5 또는 6 인 Galileo의 경우 @override 주석은 허용되지 않습니다.


0

주석은 컴파일러에 코드에 대한 메타 데이터를 제공하며 @Override 주석은 기본 클래스의 메소드를 재정의 할 때 상속시 사용됩니다. 컴파일러에게 메서드를 재정의하고 있음을 알려줍니다. 메소드의 올바른 서명을 따르지 않거나 메소드 이름의 철자를 잘못 입력하는 것과 같이 일반적인 실수를 피할 수 있습니다. 따라서 @Override 주석을 사용하는 것이 좋습니다.


0

나를 위해 @Override를 사용하면 메소드의 서명이 올바른지 확인할 수 있습니다. 주석을 넣고 메서드의 철자가 정확하지 않으면 컴파일러가 잘못된 것을 알려주는 불평을합니다.


0

간단합니다 – 수퍼 클래스에있는 메소드를 대체하려면 @Override주석을 사용하여 올바른 대체를 작성하십시오. 올바르게 재정의하지 않으면 컴파일러에서 경고합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.