回答:
メソッドをオーバーライドするたびに使用すると、2つの利点があります。コンパイラチェックを利用して、実際にメソッドをオーバーライドしていると思われるときに、メソッドをオーバーライドしていることを確認できるようにします。このようにして、メソッド名のスペルを間違えたり、パラメータを正しく一致させなかったりするという一般的な間違いを犯した場合、メソッドが実際にオーバーライドしないと警告されます。第2に、メソッドが上書きされるタイミングが明確になるため、コードが理解しやすくなります。
さらに、Java 1.6では、これを使用して、メソッドがインターフェースを実装するタイミングをマークし、同じ利点を得ることができます。別のアノテーション(など@Implements
)を使用する方が良いと思いますが、何もしないよりはましです。
このメソッドの目的は親メソッドをオーバーライドすることであるということを、コンパイル時の注意として最も役立つと思います。例として:
protected boolean displaySensitiveInformation() {
return false;
}
基本クラスのメソッドをオーバーライドする上記のメソッドのようなものがよく見られます。これは、このクラスの重要な実装の詳細です。機密情報を表示したくないのです。
このメソッドが親クラスで次のように変更されているとします。
protected boolean displaySensitiveInformation(Context context) {
return true;
}
この変更により、コンパイル時のエラーや警告は発生しませんが、サブクラスの意図した動作が完全に変更されます。
質問に答えるには、スーパークラスに同じシグネチャを持つメソッドがないことがバグを示している場合は、@ Overrideアノテーションを使用する必要があります。
ここには良い答えがたくさんあるので、別の見方をしてみましょう...
コーディングの際にやり過ぎはありません。@overrideを入力するのに費用はかかりませんが、メソッド名のスペルを間違えたり、シグネチャを少し間違えたりすると、大幅な節約になる可能性があります。
このように考えてください。ここに移動してこの投稿を入力している間、残りの人生で@overrideを入力するよりも多くの時間を費やしました。ただし、1つのエラーが発生すると、時間を節約できます。
Javaは、編集/コンパイル時に間違いを犯さないようにするためにできるすべてのことを行います。これは、包括的なテスト以外の方法では防止できない間違いのクラス全体を解決する事実上無料の方法です。
ユーザーがメソッドをオーバーライドするつもりだったときに、実際にそうしたことを確実にするために、Javaでより優れたメカニズムを思いつくことができますか?
もう1つの優れた効果は、アノテーションを提供しない場合、コンパイル時に親メソッドを誤ってオーバーライドしたことを警告することです。これは、意図していない場合に重要になる可能性があります。
@Override
注釈の使用は、一般的なプログラミングの誤りに対するコンパイル時の保護手段として機能します。スーパークラスメソッドを実際にオーバーライドしていないメソッドに注釈がある場合は、コンパイルエラーがスローされます。
これが役立つ最も一般的なケースは、基本クラスのメソッドを変更して別のパラメーターリストを持つ場合です。スーパークラスメソッドをオーバーライドするために使用されていたサブクラスのメソッドは、メソッドシグネチャが変更されたため、そのようになりません。これは、特に複雑な継承構造を扱う場合に、奇妙で予期しない動作を引き起こす可能性があります。@Override
このに対する注釈セーフガード。
コンパイラチェックを利用するには、常に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
アノテーションを使用した場合、コンパイルエラーが発生し、イベントハンドラーが実行されなかった理由を考えるのに時間を無駄にしていません。
Javaには「インターフェースのオーバーライド」などがないため、インターフェース実装の @Override は一貫していません。
インターフェース実装の @Override は、実際にはコンパイルがとにかくキャッチしないバグをキャッチしないため、役に立たない。実装者のオーバーライドが実際に何かを実行するシナリオは1つしかありません。インターフェースを実装し、インターフェースのREMOVESメソッドを実装すると、未使用の実装を削除する必要があることがコンパイル時に通知されます。新しいバージョンのインターフェースにNEWまたはCHANGEDメソッドが含まれている場合、新しいものを実装していないため、明らかにコンパイルエラーが発生することに注意してください。
インターフェース実装者の@Overrideは1.6では許可されるべきではありませんでした。Eclipseが悲しいことに、デフォルトの動作としてアノテーションを自動挿入することを選択すると、乱雑なソースファイルが多数取得されます。1.6コードを読み取るとき、メソッドが実際にスーパークラスのメソッドをオーバーライドするのか、インターフェースを実装するだけなのか、@ Overrideアノテーションからはわかりません。
スーパークラスのメソッドを実際にオーバーライドするときに@Overrideを使用することは問題ありません。
オーバーライドを意図したすべてのメソッド、およびインターフェースの実装を意図したJava 6以降のすべてのメソッドに使用するのが最善です。
まず、コンパイル時に「hashcode()
」ではなく「」のようなスペルミスをキャッチhashCode()
します。実際の原因がコードが呼び出されないことが原因である場合に、メソッドの結果がコードと一致しないように見える理由をデバッグするのは不可解なことがあります。
また、スーパークラスがメソッドシグネチャを変更する場合、古いシグネチャのオーバーライドは「孤立」する可能性があり、混乱したデッドコードとして残されます。@Override
注釈は、彼らが新しい署名と一致するように変更することができるように、これらの孤児を識別するのに役立ちます。
(非抽象)メソッドを頻繁にオーバーライドしていることに気付いた場合は、おそらくデザインを確認する必要があります。コンパイラーがエラーをキャッチしない場合に非常に役立ちます。たとえば、私はThreadLocalのinitValue()をオーバーライドしようとしています。
インターフェイスメソッド(1.6以上の機能)を実装するときに@Overrideを使用することは、私には少しやり過ぎに思えます。オーバーライドするメソッドとそうでないメソッドのロードがある場合は、おそらく設計がまた悪くなります(そして、あなたが知らない場合、エディターはどちらがそうであるかをおそらく表示します)。
インターフェースを変更すると警告が表示されるため、インターフェースの@Overrideは実際に役立ちます。
もう1つのことは、コードを読んだときに、親クラスの動作が変更されていることをより明確にすることです。デバッグに役立ちます。
また、ジョシュアブロックの著書「Effective Java(2nd edition)」の36項では、注釈の利点について詳しく説明しています。
最善の方法は、常にそれを使用することです(またはIDEに代わりに入力してもらいます)。
@Overrideの有用性は、階層を下って報告されていない親クラスの変更を検出することです。それがなければ、メソッドのシグネチャを変更してオーバーライドを忘れることができます。@ Overrideを使用すると、コンパイラーがキャッチします。
この種のセーフティネットは常に持っておくとよいでしょう。
どこでも使っています。メソッドをマークするための取り組みについては、Eclipseに任せるので、追加の取り組みはありません。
私は継続的なリファクタリングについて信心深いので...それで、私はそれをよりスムーズに動かすためにあらゆる小さなことを使います。
一貫して使用すれば、悪質なバグの大規模なクラスから保護されます。
@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
(b.first == first) && (b.second == second)
ても、私は書くでしょう。&&
==
Object::equals
はですがboolean equals(Object)
、オーバーライドされたequals
isはboolean equals(Bigram)
、オーバーライドしない別のメソッドシグネチャを持っています。@Overrideをに追加するequals
と、この失敗を検出できます。
後でstarUMLでリバースエンジニアリングを行うことはできないため、オーバーライドを使用するときは注意してください。UMLを最初に作成します。
ここの知恵は変わっているようです。今日、私はIntelliJ IDEA 9 をインストールしましたが、「欠落した@Overrideインスペクション」が実装された抽象メソッドだけでなく、実装されたインターフェイスメソッドもキャッチするようになりました。私の雇用主のコードベースと自分のプロジェクトでは、前者の@Overrideのみを使用する習慣がありました-実装された抽象メソッドです。しかし、習慣を再考すると、どちらの場合でもアノテーションを使用するメリットが明らかになります。より冗長ではありますが、インターフェイスメソッド名が変更され、派生クラスの実装予定のメソッドが孤立するという、脆弱な基本クラスの問題(C ++関連の例ほど重大ではない)から保護されます。
もちろん、このシナリオはほとんどが誇張です。派生クラスはコンパイルされなくなり、名前が変更されたインターフェイスメソッドの実装がなくなりました。今日では、Rename Methodリファクタリング操作を使用して、コードベース全体を一括で処理する可能性があります。
IDEAのインスペクションは実装されたインターフェイスメソッドを無視するように構成できないので、今日は、私の習慣とチームのコードレビュー基準の両方を変更します。
アノテーション@Overrideは、開発者が親クラスまたはインターフェースの正しいメソッドをオーバーライドする必要があるかどうかを確認するのに役立ちます。スーパーのメソッドの名前が変更されると、コンパイラーはその場合に通知できます。これは、スーパーおよびサブクラスとの整合性を保つためだけです。
ところで、サブクラスで@Overrideアノテーションをアナウンスしなかったが、スーパーのいくつかのメソッドをオーバーライドした場合、関数は@Overrideを使用してそのメソッドとして機能できます。ただし、このメソッドは、スーパーのメソッドが変更されたときに開発者に通知できません。開発者の目的がわからなかったため-superのメソッドをオーバーライドするか、新しいメソッドを定義しますか?
そのため、ポリモーフィズムを利用するためにそのメソッドをオーバーライドする場合は、メソッドの上に@Overrideを追加することをお勧めします。