@Override
Java のアノテーション を使用するためのベスト プラクティスとその理由は何ですか?
@Override
オーバーライドされたすべてのメソッドに注釈を付けるのはやり過ぎのようです。を使用する必要がある特定のプログラミング状況と、 を使用し@Override
てはならない状況はあり@Override
ますか?
@Override
Java のアノテーション を使用するためのベスト プラクティスとその理由は何ですか?
@Override
オーバーライドされたすべてのメソッドに注釈を付けるのはやり過ぎのようです。を使用する必要がある特定のプログラミング状況と、 を使用し@Override
てはならない状況はあり@Override
ますか?
メソッドをオーバーライドするたびに使用すると、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 つの優れた効果は、注釈を指定しないと、コンパイル時に親メソッドを誤ってオーバーライドしたことを警告することです。
タグはいつも使ってます。これは、私が犯す可能性のある小さな間違いを検出するための単純なコンパイル時のフラグです。
tostring()
代わりに次のようなものをキャッチしますtoString()
大規模なプロジェクトでは、小さなことが役立ちます。
注釈を使用する@Override
と、一般的なプログラミングの誤りに対するコンパイル時の保護手段として機能します。スーパークラス メソッドを実際にオーバーライドしていないメソッドに注釈がある場合、コンパイル エラーがスローされます。
これが役立つ最も一般的なケースは、基本クラスのメソッドを変更して別のパラメーター リストを持つ場合です。スーパークラス メソッドをオーバーライドするために使用されたサブクラスのメソッドは、メソッド シグネチャが変更されたため、オーバーライドされなくなりました。これは、特に複雑な継承構造を扱う場合に、奇妙で予期しない動作を引き起こすことがあります。@Override
注釈はこれを防ぎます。
コンパイラ チェックを利用するには、常に Override アノテーションを使用する必要があります。ただし、Java コンパイラ 1.5 では、インターフェイス メソッドをオーバーライドするときにこの注釈を使用できないことを忘れないでください。それを使用して、クラスメソッドをオーバーライドすることができます (abstract または not)。
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
アノテーションを使用した場合、コンパイル エラーが発生し、イベント ハンドラーが実行されていない理由を考えるのに時間を無駄にしませんでした。
Javaには「インターフェースのオーバーライド」などがないため、インターフェース実装の@Overrideには一貫性がありません。
インターフェイス実装での@Overrideは、実際にはコンパイルでキャッチされないバグをキャッチしないため、役に立ちません。実装者のオーバーライドが実際に何かを行う、とてつもないシナリオが 1 つだけあります。インターフェイスを実装し、インターフェイスの REMOVES メソッドを実装すると、未使用の実装を削除する必要があることがコンパイル時に通知されます。インターフェイスの新しいバージョンに NEW または CHANGED メソッドがある場合、新しいものを実装していないため、明らかにコンパイル エラーが発生することに注意してください。
インターフェイス実装者の @Override は 1.6 では決して許可されるべきではありませんでした。悲しいことに、Eclipse がデフォルトの動作として注釈を自動挿入することを選択したため、多くの雑然としたソース ファイルが得られます。1.6 コードを読むと、@Override アノテーションからは、メソッドが実際にスーパークラスのメソッドをオーバーライドするのか、単にインターフェイスを実装するだけなのかを確認できません。
スーパークラスのメソッドを実際にオーバーライドするときに @Override を使用しても問題ありません。
オーバーライドとして意図されたすべてのメソッド、およびJava 6+、インターフェースの実装として意図されたすべてのメソッドに使用するのが最善です。
まず、コンパイル時hashcode()
に " " ではなく" " などのスペルミスを検出します。hashCode()
コードが呼び出されないことが本当の原因である場合、メソッドの結果がコードと一致しないように見える理由をデバッグするのは困惑する可能性があります。
また、スーパークラスがメソッド シグネチャを変更すると、古いシグネチャのオーバーライドが「孤立」し、混乱を招くデッド コードとして取り残される可能性があります。@Override
注釈は、これらのオーファンを識別して、新しい署名に一致するように変更できるようにするのに役立ちます。
もう 1 つのことは、親クラスの動作を変更していることをコードを読むときにより明確にすることです。デバッグに役立ちます。
また、Joshua Block の著書『Effective Java』(第 2 版) の項目 36 で、アノテーションの利点について詳しく説明しています。
(抽象的ではない) メソッドを頻繁にオーバーライドしている場合は、おそらく設計を見直す必要があります。これは、コンパイラがエラーをキャッチできない場合に非常に役立ちます。たとえば、私が行った ThreadLocal で initValue() をオーバーライドしようとしています。
インターフェース メソッド (1.6 以降の機能) を実装するときに @Override を使用するのは、私にとってはやり過ぎのようです。オーバーライドするメソッドとオーバーライドしないメソッドがたくさんある場合は、おそらくまた悪い設計です (そして、わからない場合は、エディターがどれがどれであるかを表示する可能性があります)。
インターフェイスを変更すると警告が表示されるため、インターフェイスの @Override は実際に役立ちます。
メソッドが別のメソッドをオーバーライドするとき、またはメソッドがインターフェイスに署名を実装するときはいつでも。
@Override
注釈は、実際に何かをオーバーライドしたことを保証します。注釈がないと、スペルミスやパラメーターの型と数の違いが生じる危険があります。
インターフェース メソッドを実装するときに @Override を使用してもまったく意味がありません。その場合、それを使用するメリットはありません。コンパイラはすでに間違いを検出するため、不必要に混乱するだけです。
一貫して使用すれば、悪質なバグの大規模なクラスから保護されます。
@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
毎回利用しています。これは、1 年後にコードを再確認したときに、最初に何を考えていたかを忘れてしまったときに、何が起こっているのかをすばやく把握するために使用できる情報です。
最善の方法は、常にそれを使用することです (または、IDE に入力してもらいます)。
@Override の有用性は、階層を下って報告されていない親クラスの変更を検出することです。これがないと、メソッド シグネチャを変更してそのオーバーライドを変更するのを忘れる可能性があります。@Override を使用すると、コンパイラがそれをキャッチします。
この種のセーフティ ネットは、常に用意しておくとよいでしょう。
私はどこでもそれを使用します。メソッドのマーキング作業については、Eclipse に任せているので、追加の作業は必要ありません。
私は継続的なリファクタリングについて信心深い....だから、私はそれをよりスムーズに進めるためにあらゆる小さなことを使用します.
後で starUML でリバース エンジニアリングを行うことはできないため、Override を使用する場合は注意してください。最初にUMLを作成します。
ここの知恵が変わっているようです。今日、私はIntelliJ IDEA 9 をインストールし、その「@Override インスペクションの欠落」が、実装された抽象メソッドだけでなく、実装されたインターフェース メソッドもキャッチするようになったことに気付きました。私の雇用主のコードベースと私自身のプロジェクトでは、@Override を前者 (実装された抽象メソッド) にのみ使用する習慣が長い間ありました。ただし、習慣を考え直すと、両方の場合にアノテーションを使用するメリットが明らかになります。より冗長であるにもかかわらず、インターフェイス メソッド名が変更され、派生クラスで実装されるメソッドが孤立するという脆弱な基本クラスの問題 (C++ 関連の例ほど重大ではない) から保護します。
もちろん、このシナリオはほとんど誇張です。派生クラスはコンパイルされなくなり、名前が変更されたインターフェイス メソッドの実装がなくなります。今日では、メソッドの名前変更リファクタリング操作を使用して、コード ベース全体にまとめて対処する可能性があります。
IDEA のインスペクションは、実装されたインターフェイス メソッドを無視するように構成できないため、今日は私の習慣とチームのコード レビュー基準の両方を変更します。
注釈 @Override は、開発者が親クラスまたはインターフェースの正しいメソッドをオーバーライドするかどうかを確認するために使用されます。スーパーのメソッドの名前が変更されると、コンパイラはそのケースを通知できます。これは、スーパーおよびサブクラスとの一貫性を維持するためだけです。
ところで、サブクラスで注釈 @Override をアナウンスしなかったが、スーパーのいくつかのメソッドをオーバーライドした場合、関数は @Override を使用したものとして機能します。ただし、このメソッドは、スーパーのメソッドが変更されたときに開発者に通知できません。開発者の目的を知らなかったので、スーパーのメソッドをオーバーライドするか、新しいメソッドを定義しますか?
そのため、ポリモーフィズムを利用するためにそのメソッドをオーバーライドしたい場合は、メソッドの上に @Override を追加することをお勧めします。
メソッドがいつオーバーライドされているかを識別するために、できる限りそれを使用します。Scala プログラミング言語を見ると、override キーワードもあります。便利だと思います。
オーバーライドしているメソッド名に間違ったスペルを使用したときに、(コンパイラーが) キャッチできるようにします。
私にとって @Override は、メソッドの署名が正しいことを保証します。注釈を入れたときにメソッドのスペルが正しくない場合、コンパイラは何かが間違っていることを知らせて文句を言います。
オーバーライド注釈は、親クラスのメソッドを実際にオーバーライドしているかどうかを確認するために、コンパイラを利用するために使用されます。メソッド名のスペルミス、パラメータが正しく一致していないなどの間違いがあった場合に通知するために使用されます
許可されている場合はいつでも @override をコーディングするのが最善だと思います。コーディングに役立ちます。ただし、SDK 5 または 6 のいずれかの Eclipse Helios では、実装されたインターフェイス メソッドの @override アノテーションが許可されていることに注意してください。ガリレオに関しては、5 または 6 のいずれかで、@override アノテーションは使用できません。
シンプル - スーパークラスに存在するメソッドをオーバーライドする場合は、@Override
アノテーションを使用して正しいオーバーライドを行います。正しくオーバーライドしないと、コンパイラから警告が表示されます。