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


498

Javaの@Override注釈を使用するためのベストプラクティスとは何ですか。なぜですか。

オーバーライドされたすべてのメソッドに@Override注釈を付けるのはやり過ぎのようです。を使用する@Override必要がある特定のプログラミング状況と、を使用してはならないその他の状況はあります@Overrideか?

回答:


515

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

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


4
「理解しやすい」と同じように、IDEは@Overrideアノテーションを見つけ、オーバーライドメソッドにエディターで視覚的にフラグを立てます。
ボブ・クロス

47
一部のIDEは、@ Overrideアノテーションが欠落しているオーバーライドされたメソッドにフラグを立てます。
ジェイR.

20
他の利点は、親クラスが変更された場合、コンパイラーが子クラスも更新されていることを確認することです。
デビッド

4
@ジェイ・R:そうです。実際のところ、たとえばEclipseは、@ Overrideがない場合は自動的に追加することもできます。
sleske 2009年

32
インターフェースから来るメソッドの@Overridesの1.5から1.6への明らかに文書化されていない変更のために他の誰かがここに来た場合、bugs.sun.com / bugdatabase / view_bug.do?bug_id = 5008260が対応するバグのようです。(指摘してくれてありがとう、Dave L.!)
Henrik Heimbuerger

110

このメソッドの目的は親メソッドをオーバーライドすることであるということを、コンパイル時の注意として最も役立つと思います。例として:

protected boolean displaySensitiveInformation() {
  return false;
}

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

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

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

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

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


46

ここには良い答えがたくさんあるので、別の見方をしてみましょう...

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

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

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

ユーザーがメソッドをオーバーライドするつもりだったときに、実際にそうしたことを確実にするために、Javaでより優れたメカニズムを思いつくことができますか?

もう1つの優れた効果は、アノテーションを提供しない場合、コンパイル時に親メソッドを誤ってオーバーライドしたことを警告することです。これは、意図していない場合に重要になる可能性があります。


3
「コーディングの際にやり過ぎはありません。」私はこれに同意します。これが私が動的言語を非常に間違っていると思う理由です(ただし、私の支払った作業の100%は現在ルビーで書かれています)。
Dan Rosenstark、2010年

4
+1:おそらく、オーバーライドのミスによって引き起こされたバグが10個ありました。それらのいずれかを見つけるのに必要な時間は、オーバーライドメソッドのすべてで@Overrideを入力する時間を簡単に超えてしまうでしょう。また、@ Overrideが負担になる場合は、継承を使いすぎている可能性があります。
ローレンスドル

7
非常に現実的な欠点の1つは、カタツムリを散らかすことによってコードを読みにくくすることです。おそらくこれは私のIDEのせいですが、私はこれを自分で経験しました。
modをうまく処理する

9
@phyzome「カタツムリ」が扱いにくい場合は、十分な数のコメントの近くのどこも使用していません。適切なホバーテキストとjavadocsを提供するために、メソッドヘッダーの上の1行だけにする必要があります。問題はカタツムリではなく、それはあなたの読書習慣だと私は言っていると思います。コード内のすべてのかっこもあなたを悩ませていますか?
ビルK

4
はい、コーディングには行き過ぎがあります。コードが明らかに行うことを単にオウムするコメントを書くとき。
Ants 2012年

22

いつもタグを使っています。これは、私が犯す可能性のある小さな間違いを見つけるための単純なコンパイル時フラグです。

それは物事が好きキャッチしますtostring()代わりにtoString()

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


18

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

これが役立つ最も一般的なケースは、基本クラスのメソッドを変更して別のパラメーターリストを持つ場合です。スーパークラスメソッドをオーバーライドするために使用されていたサブクラスのメソッドは、メソッドシグネチャが変更されたため、そのようになりません。これは、特に複雑な継承構造を扱う場合に、奇妙で予期しない動作を引き起こす可能性があります。@Overrideこのに対する注釈セーフガード。


ベストアンサー。短くて甘い。「セーフガード」の仕組みについて説明してもらえれば幸いです。
djangofan

説明するのは簡単です。間違いを犯した場合(インターフェース、抽象クラス、またはサブクラスを変更した場合)、警告(Eclipseなど)または@Overrideが機能していないことを示すコンパイル時エラーが表示されます。実際のエラーメッセージは何が変更されたかに依存しますが、Eclipse(たとえば)では、問題があることが非常にすぐにわかります。小さな赤いジグザグの下線が表示され、問題のあるテキストにカーソルを合わせると、何が問題なのかがわかります。それをグッドバリューと呼んでいます
古里一郎2012年

14

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

一部のIDEは、Eclipseのように、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

Javaには「インターフェースのオーバーライド」などがないため、インターフェース実装の @Override は一貫していません。

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

インターフェース実装者の@Overrideは1.6では許可されるべきではありませんでした。Eclipseが悲しいことに、デフォルトの動作としてアノテーションを自動挿入することを選択すると、乱雑なソースファイルが多数取得されます。1.6コードを読み取るとき、メソッドが実際にスーパークラスのメソッドをオーバーライドするのか、インターフェースを実装するだけなのか、@ Overrideアノテーションからはわかりません。

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


2
その点についてはさまざまな意見があります。stackoverflow.com/questions/212614/…を参照してください。
sleske 2009年

8

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

まず、コンパイル時に「hashcode()」ではなく「」のようなスペルミスをキャッチhashCode()します。実際の原因がコードが呼び出されないことが原因である場合に、メソッドの結果がコードと一致しないように見える理由をデバッグするのは不可解なことがあります。

また、スーパークラスがメソッドシグネチャを変更する場合、古いシグネチャのオーバーライドは「孤立」する可能性があり、混乱したデッドコードとして残されます。@Override注釈は、彼らが新しい署名と一致するように変更することができるように、これらの孤児を識別するのに役立ちます。


7

(非抽象)メソッドを頻繁にオーバーライドしていることに気付いた場合は、おそらくデザインを確認する必要があります。コンパイラーがエラーをキャッチしない場合に非常に役立ちます。たとえば、私はThreadLocalのinitValue()をオーバーライドしようとしています。

インターフェイスメソッド(1.6以上の機能)を実装するときに@Overrideを使用することは、私には少しやり過ぎに思えます。オーバーライドするメソッドとそうでないメソッドのロードがある場合は、おそらく設計がまた悪くなります(そして、あなたが知らない場合、エディターはどちらがそうであるかをおそらく表示します)。


2
実際には、オーバーライドされたインターフェイスメソッドにも適しています。たとえば、古い非推奨のメソッドをインターフェイスから削除する場合、そのメソッドもすべての実装クラスから削除する必要があります。@ overrideを使用すれば、簡単に見つけることができます。
ドミニクサンドジャジャ2010


7

もう1つのことは、コードを読んだときに、親クラスの動作が変更されていることをより明確にすることです。デバッグに役立ちます。

また、ジョシュアブロックの著書「Effective Java(2nd edition)」の36項では、注釈の利点について詳しく説明しています。


はい、確かに-アイテム36 :)
Chris Kimpton

6

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


6
@Overrideインターフェースでを使用すると、インターフェースのメソッドが削除されたときに通知されます。
Alex B

@Alex:インターフェースのメソッドを削除することは、それらを追加するような、重大な変更です。インターフェイスが公開されると、それを使用するすべてのコードを完全に制御しない限り、実質的にロックされます。
ローレンスドル

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


Javaでの演算子の優先順位の規則はわかりませんが、equalsメソッドがBUUUUUUUUUUUUGを叫んでいます!よりも優先順位が低く(b.first == first) && (b.second == second)ても、私は書くでしょう。&&==
2009年

あなたのリンクがそのページの有用な部分をカバーする「あなたは購読しなければならない」というメッセージを示していることをご存知ですか?
Adriano Varoli Piazza

@アドリアーノ:ごめんね!どうしようもない!私が「答え」を書いたとき、それは利用可能でした。本を購入してください。それを持っている価値があります!!
jai

5
equalsメソッドはオーバーライドしません:オリジナルObject::equalsはですがboolean equals(Object)、オーバーライドされたequalsisはboolean equals(Bigram)、オーバーライドしない別のメソッドシグネチャを持っています。@Overrideをに追加するequalsと、この失敗を検出できます。
Ming-Tang

3

後でstarUMLでリバースエンジニアリングを行うことはできないため、オーバーライドを使用するときは注意してください。UMLを最初に作成します。


2

ここの知恵は変わっているようです。今日、私はIntelliJ IDEA 9 をインストールしましたが、「欠落した@Overrideインスペクション」が実装された抽象メソッドだけでなく、実装されたインターフェイスメソッドもキャッチするようになりました。私の雇用主のコードベースと自分のプロジェクトでは、前者の@Overrideのみを使用する習慣がありました-実装された抽象メソッドです。しかし、習慣を再考すると、どちらの場合でもアノテーションを使用するメリットが明らかになります。より冗長ではありますが、インターフェイスメソッド名が変更され、派生クラスの実装予定のメソッドが孤立するという、脆弱な基本クラスの問題(C ++関連の例ほど重大ではない)から保護されます。

もちろん、このシナリオはほとんどが誇張です。派生クラスはコンパイルされなくなり、名前が変更されたインターフェイスメソッドの実装がなくなりました。今日では、Rename Methodリファクタリング操作を使用して、コードベース全体を一括で処理する可能性があります。

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


2

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

ところで、サブクラスで@Overrideアノテーションをアナウンスしなかったが、スーパーのいくつかのメソッドをオーバーライドした場合、関数は@Overrideを使用してそのメソッドとして機能できます。ただし、このメソッドは、スーパーのメソッドが変更されたときに開発者に通知できません。開発者の目的がわからなかったため-superのメソッドをオーバーライドするか、新しいメソッドを定義しますか?

そのため、ポリモーフィズムを利用するためにそのメソッドをオーバーライドする場合は、メソッドの上に@Overrideを追加することをお勧めします。


1

メソッドがオーバーライドされているときを識別するために、それをできる限り使用します。Scalaプログラミング言語を見ると、それらにはオーバーライドキーワードもあります。重宝しています。


0

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


0

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


0

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


0

アノテーションはコードに関するメタデータをコンパイラに提供し、基本クラスのメソッドをオーバーライドするときに継承の場合はアノテーション@Overrideが使用されます。メソッドをオーバーライドしていることをコンパイラに伝えます。これにより、メソッドの適切なシグネチャに従わなかったり、メソッド名のスペルを間違えたりするなど、よくある間違いを回避できます。@ Overrideアノテーションを使用することをお勧めします。


0

私にとって@Overrideは、メソッドの署名が正しいことを保証します。注釈を入力し、メソッドのスペルが正しくない場合、コンパイラーは何か問題があることを知らせるメッセージを表示します。


0

シンプル–スーパークラスにあるメソッドをオーバーライドする場合は、@Overrideアノテーションを使用して正しいオーバーライドを作成します。正しくオーバーライドしないと、コンパイラーから警告が出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.