web-dev-qa-db-ja.com

Javaの@Overrideアノテーションを使用するのはいつですか。その理由は何ですか?

Javaの@Overrideアノテーションを使うためのベストプラクティスは何ですか、またその理由は何ですか?

すべてのオーバーライドされたメソッドを@Overrideアノテーションでマークするのはやり過ぎるようです。 @Overrideを使用することを要求する特定のプログラミング状況や、@Overrideを使用してはいけないその他の状況がありますか?

498
Alex B

2つの利点のためにメソッドをオーバーライドするたびにそれを使用してください。コンパイラーチェックを利用して、自分がいると思ったときに実際にメソッドをオーバーライドしていることを確認できるようにします。このようにして、メソッド名のスペルを間違えたり、パラメータを正しく一致させなかったりするという一般的な間違いをした場合、あなたが思っているようにメソッドが実際にオーバーライドしないことを警告されます。第二に、メソッドが上書きされたときにより明白になるため、コードが理解しやすくなります。

さらに、Java 1.6では、メソッドがインタフェースを実装するタイミングをマークするためにそれを使用して同じ利点を得ることができます。 @Implementsのように別のアノテーションを付けるほうがいいと思いますが、何もないよりはましです。

515
Dave L.

私は、メソッドの意図が親メソッドをオーバーライドすることであることをコンパイル時のリマインダとして最も有用であると思います。例として:

protected boolean displaySensitiveInformation() {
  return false;
}

あなたは基本クラスのメソッドをオーバーライドする上記のメソッドのようなものをしばしば見るでしょう。これはこのクラスの重要な実装の詳細です - 私たちは機密情報を表示したくないです。

このメソッドが親クラスで次のように変更されたとします。

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

この変更によってコンパイル時のエラーや警告が発生することはありませんが、サブクラスの意図された動作が完全に変更されます。

質問に答えるには、スーパークラス内に同じシグネチャを持つメソッドがないことがバグを示している場合は、@ Overrideアノテーションを使用する必要があります。

110
jon

ここにはたくさんの良い答えがあります、それで私はそれを見るための別の方法を提供しましょう...

コーディングしているときにやり過ぎはありません。 @overrideを入力してもコストはかかりませんが、メソッド名のスペルを間違えたり、シグネチャを少し間違えたりした場合、節約になる可能性があります。

このように考えてみてください。ここに移動してこの投稿を入力したときに、残りの人生に@overrideと入力するよりも多くの時間を費やしました。しかし、それが防ぐ1つのエラーはあなたに時間を節約することができます。

編集/コンパイル時に間違いを犯さないようにするために、Javaは全力を尽くします。これは、包括的なテスト以外では防ぐことができないクラス全体の間違いを解決するための事実上無料の方法です。

ユーザーがメソッドをオーバーライドしようとしたときに、実際にそうしたことを保証するために、Javaでより良いメカニズムを思いついたでしょうか。

注釈を付けないと、コンパイル時に誤って親メソッドをオーバーライドしてしまうという警告が表示されることがあります。そうしないと意味がある場合があります。

46
Bill K

私はいつもタグを使います。それは私がするかもしれない小さな間違いを捕らえるための単純なコンパイル時フラグです。

tostring()ではなくtoString()のようなものをキャッチします。

ささいなことは大規模なプロジェクトに役立ちます。

22
jjnguy

@Overrideアノテーションを使用すると、一般的なプログラミングミスに対するコンパイル時の保護手段として機能します。実際にスーパークラスのメソッドをオーバーライドしていないメソッドに注釈がある場合は、コンパイルエラーが発生します。

これが便利な最も一般的なケースは、基本クラスのメソッドを変更して別のパラメータリストを作成する場合です。スーパークラスのメソッドをオーバーライドするために使用されていたサブクラス内のメソッドは、メソッドシグネチャが変更されたために、もはやそのようにはされません。特に複雑な継承構造を扱うとき、これは時々奇妙で予想外の振舞いを引き起こすことができます。 @Overrideアノテーションはこれを防ぎます。

18
toluju

コンパイラチェックを利用するには、常にOverrideアノテーションを使用する必要があります。しかし、Java Compiler 1.5がインターフェースメソッドをオーバーライドするときにこのアノテーションを許可しないことを忘れないでください。あなたはクラスメソッドをオーバーライドするためにそれを使うことができます(抽象かどうか)。

Eclipseのように、Java 1.6ランタイム以上で構成されているIDEでも、Java 1.5とのコンプライアンスを維持し、上記のように@overrideの使用を許可しないものがあります。この動作を回避するには、プロジェクトプロパティ - > Javaコンパイラ - >「プロジェクト固有の設定を有効にする」をチェックします - >「コンパイラの準拠レベル」= 6.0以上を選択します。

ベースがインターフェースまたはクラスの場合は、メソッドを個別にオーバーライドするたびにこのアノテーションを使用します。

これは、イベントハンドラをオーバーライドしているのに何も起こらないと思っているときなど、一般的なエラーを回避するのに役立ちます。あるUIコンポーネントにイベントリスナを追加したいとします。

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

上記のコードはコンパイルされて実行されますが、実際に基本メソッドmouseEntered(MouseEvent ev)をオーバーライドしていないため、someUIComponent内でマウスを動かした場合、「do something」コードはrunと表示されます。あなただけの新しいパラメータなしのメソッドmouseEntered()を作成します。そのコードの代わりに@Overrideアノテーションを使用した場合はコンパイルエラーが発生しているので、イベントハンドラが実行されていない理由を考えて時間を無駄にしていません。

14
user174340

オーバーライドを意図したすべてのメソッド、およびインターフェースの実装を意図したすべてのメソッドに対してJava 6+で使用するのが最善です。

まず、コンパイル時に "hashcode()"ではなく "hashCode()"のようなスペルミスをキャッチします。本当の原因はあなたのコードが決して呼び出されないということであるのになぜあなたのメソッドの結果があなたのコードと一致しないように見えるかをデバッグするのは面倒かもしれません。

また、スーパークラスがメソッドのシグネチャを変更した場合、古いシグネチャのオーバーライドが "孤立"し、デッドコードが混乱する可能性があります。 @Overrideアノテーションは、あなたがこれらの孤児を識別するのに役立ちますので、それらは新しい署名と一致するように修正することができます。

8
erickson

インターフェースの実装の@Override は、Javaでは「インターフェースをオーバーライドする」というようなことがないので矛盾しています。

interface implementation の@Overrideは、実際にはコンパイルがキャッチしないというバグをキャッチしないため、役に立ちません。実装者へのオーバーライドが実際に何かをするシナリオは1つしかありません。インタフェースを実装し、インタフェースREMOVESメソッドを実装する場合は、未使用の実装を削除するようにコンパイル時に通知されます。新しいバージョンのインターフェースにNEWまたはCHANGEDメソッドがある場合は、新しいものを実装していないため、明らかにコンパイルエラーが発生します。

1.6でインターフェース実装者への@Overrideは許可されるべきではありませんでした、そしてEclipseがデフォルトの振る舞いとしてアノテーションを自動挿入することを残念に選択すると、たくさんの雑然としたソースファイルを得ます。 1.6コードを読むとき、あるメソッドが実際にスーパークラスのメソッドをオーバーライドするのか、それとも単にインターフェースを実装するのかは@Overrideアノテーションからはわかりません。

スーパークラスのメソッドを実際にオーバーライドするときに@Overrideを使用するのは問題ありません。

8
Rune

それがするもう一つのことは、それがコードを読むとき、それが親クラスの振る舞いを変えていることをより明白にするということです。デバッグに役立ちます。

また、Joshua Blockの著書Effective Java(2nd edition)の項目36に、注釈の利点に関する詳細が記載されています。

7
Diastrophism

インターフェースを変更すると警告が表示されるので、インターフェースの@Overrideは実際には便利です。

7

自分自身が(非抽象)メソッドを頻繁にオーバーライドしていることに気付いた場合は、おそらく自分のデザインを見たいと思うでしょう。コンパイラがそうでなければエラーを捕捉できない場合に非常に便利です。たとえば、ThreadLocalのinitValue()をオーバーライドしようとしましたが、これは完了です。

インターフェースメソッド(1.6+の機能)を実装するときに@Overrideを使うのは私には少しやり過ぎです。いくつかのメソッドがオーバーライドし、いくつかのメソッドがオーバーライドしないメソッドがたくさんある場合、そのデザインはおそらく再び悪いでしょう(そしてあなたのエディタはおそらくあなたが知らないならどちらがどれを示すでしょう)。

インターフェースメソッドを実装するときに@Overrideを使用しても意味がありません。その場合それを使用することに利点はありません - コンパイラはすでにあなたの間違いを捕らえるでしょう、それでそれはただ不必要な雑然としています。

6
Steve R.

あるメソッドが別のメソッドをオーバーライドするとき、またはメソッドがインターフェース内でシグニチャーを実装するときはいつでも。

@Overrideアノテーションはあなたが実際に何かをオーバーライドしたことをあなたに保証します。注釈がないと、スペルミスやパラメータの種類と数の違いが生じる危険があります。

6
Greg Mattes
  • メソッド宣言でのみ使用されます。
  • 注釈付きメソッド宣言がスーパータイプの宣言をオーバーライドすることを示します。

一貫して使用されれば、それはあなたを大規模な種類の悪意のあるバグから保護します。

これらのバグを回避するには、@ 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

5
jai

毎回使います。 1年のうちにコードを再訪したときに何が起こっているのかをすばやく把握するために使用できるより多くの情報であり、私が最初に考えていたことを忘れていました。

5
Hank Gay

私はいたるところでそれを使っています。メソッドをマークするための努力の話題については、Eclipseに私に任せてもらいます。それ以上の努力は必要ありません。

私は継続的なリファクタリングについては宗教的です....だから、私はそれをより円滑に進めるためにあらゆることをやるつもりです。

5
willCode4Beer

最善の方法は、常にそれを使用することです(またはIDEでそれらを埋めてもらう)。

@Overrideの有用性は、階層の下位に報告されていない親クラスの変更を検出することです。それがなければ、メソッドシグネチャを変更してそのオーバーライドを変更することを忘れることができます。@ Overrideを使用すると、コンパイラはそれをキャッチします。

そのようなセーフティネットは常に持っておくのがいいです。

5
David Pierre

オーバーライドを使用するときは注意してください。後でstarUMLでリバースエンジニアを行うことはできません。最初にumlを作ります。

3
Horatiu Jeflea

ここの知恵は変わりつつあるようです。今日、私は IntelliJ IDEA 9をインストールし、その " missing @Override inspection "が抽象メソッドを実装するだけでなく、インタフェースメソッドも実装するようになったことに気づきました。私の雇用主のコードベースと私自身のプロジェクトでは、以前に実装された抽象メソッドに@Overrideのみを使う習慣がありました。しかし、習慣を考え直すと、どちらの場合もアノテーションを使用するメリットは明らかになります。より冗長にもかかわらず、インタフェースメソッド名が変更される 壊れやすい基底クラス 問題(Graveほどではない)から保護し、派生クラスの実装メソッドを孤立させます。

もちろん、このシナリオは大体誇張です。派生クラスはコンパイルされなくなり、現在は名前が変更されたインタフェースメソッドの実装が欠如しています。今日では、コードベース全体をまとめてアドレス指定するために メソッド名の変更 リファクタリング操作を使用します。

IDEAの検査は実装されたインターフェースメソッドを無視するように設定することはできないため、今日は私の習慣とチームのコードレビュー基準の両方を変更します。

2
seh

アノテーション@Overrideは、開発者が親クラスまたはインタフェースの正しいメソッドをオーバーライドするかどうかを確認するのに役立ちます。 superのメソッドの名前が変わると、コンパイラはそのケースを通知できます。これはsuperとサブクラスとの一貫性を保つためだけのものです。

ところで、我々がサブクラスでアノテーション@Overrideを発表しなかったが、我々がスーパーのいくつかのメソッドをオーバーライドするならば、関数は@Overrideでそのものとして働くことができます。しかし、このメソッドは、スーパーのメソッドが変更されたときに開発者に通知することはできません。それは開発者の目的を知らなかったので - スーパーのメソッドをオーバーライドするか、新しいメソッドを定義しますか?

そのため、Polymorphismを利用するためにそのメソッドをオーバーライドしたい場合は、メソッドの上に@Overrideを追加することをお勧めします。

2
lzlstyle

メソッドがオーバーライドされているときを識別するために、できるだけそれを使います。 Scalaプログラミング言語を見ると、それらにはoverrideキーワードもあります。私はそれが役に立つと思います。

1
Berlin Brown

許可されているときはいつでも@overrideをコーディングするのが最善だと思います。コーディングに役立ちます。ただし、注意する必要がありますが、ecipse Helios(sdk 5または6)では、実装されたインターフェースメソッドの@overrideアノテーションは許可されています。 Galileoの場合は5または6、@overrideアノテーションは許可されていません。

0
lwpro2

私にとって@Overrideは、メソッドのシグネチャが正しいことを保証します。注釈を入れてもメソッドのスペルが正しくないと、コンパイラは何かが間違っていることを知らせて文句を言います。

0
Dale

単純 - スーパークラスに存在するメソッドをオーバーライドしたい場合は、@Overrideアノテーションを使用して正しいオーバーライドを行います。正しく上書きしないと、コンパイラーは警告を出します。

0
Sree

オーバーライドしているメソッド名に間違ったスペルを使用したことがある場合は、それ(つまり、コンパイラ)がキャッチすることができます。

0
JeeBee

オーバーライドアノテーションは、実際に親クラスからメソッドをオーバーライドしているかどうかを確認するために、コンパイラを利用するために使用されます。メソッド名のスペルミスや、パラメータが正しく一致していないなどの間違いを犯した場合に通知するために使用されます。

0
Siva

アノテーションはコードに関するメタデータをコンパイラに提供します。アノテーション@Overrideは、継承の場合に基本クラスのメソッドをオーバーライドするときに使用されます。メソッドをオーバーライドしていることをコンパイラに伝えるだけです。メソッドの適切なシグニチャに従わなかったり、メソッドの名前を誤って入力したりするなど、私たちがすることができるいくつかの種類の一般的なミスを回避できます。そのため、@ Overrideアノテーションを使用することをお勧めします。

0
gprathour