Wann verwenden Sie die @ Override-Annotation von Java und warum?


498

Was sind die Best Practices für die Verwendung der Java- @OverrideAnnotation und warum?

Es scheint übertrieben, jede einzelne überschriebene Methode mit der @OverrideAnmerkung zu markieren . Gibt es bestimmte Programmiersituationen, die die Verwendung von @Overrideund andere erfordern, die das niemals verwenden sollten @Override?

Antworten:


515

Verwenden Sie es jedes Mal, wenn Sie eine Methode mit zwei Vorteilen überschreiben. Tun Sie dies, damit Sie die Compilerprüfung nutzen können, um sicherzustellen, dass Sie eine Methode tatsächlich überschreiben, wenn Sie glauben, dass Sie es sind. Auf diese Weise werden Sie gewarnt, wenn Sie einen häufigen Fehler machen, einen Methodennamen falsch zu schreiben oder nicht korrekt mit den Parametern übereinzustimmen, dass Ihre Methode nicht so überschreibt, wie Sie denken. Zweitens erleichtert dies das Verständnis Ihres Codes, da es offensichtlicher ist, wenn Methoden überschrieben werden.

Darüber hinaus können Sie in Java 1.6 damit markieren, wann eine Methode eine Schnittstelle mit denselben Vorteilen implementiert. Ich denke, es wäre besser, eine separate Anmerkung (wie @Implements) zu haben, aber es ist besser als nichts.


4
In Anlehnung an "leichter zu verstehen" erkennen die IDEs die Annotation @Override und kennzeichnen die überschreibende Methode im Editor visuell.
Bob Cross

47
Einige IDEs kennzeichnen eine überschriebene Methode, bei der auch die Annotation @Override fehlt.
Jay R.

20
Der andere Vorteil besteht darin, dass der Compiler bei Änderungen der übergeordneten Klasse sicherstellt, dass auch die untergeordneten Klassen aktualisiert wurden.
David

4
@ Jay R.: Richtig. Tatsächlich kann z. B. Eclipse den @Override sogar automatisch hinzufügen, wenn er fehlt.
Sleske

32
Für den Fall, dass jemand anderes wegen der anscheinend undokumentierten Änderung von 1.5 auf 1.6 für @Overrides für Methoden von Schnittstellen hierher gekommen ist, scheint bugs.sun.com/bugdatabase/view_bug.do?bug_id=5008260 der entsprechende Fehler zu sein. (Danke für den Hinweis, Dave L.!)
Henrik Heimbuerger

110

Ich denke, es ist am nützlichsten, um zur Kompilierungszeit daran zu erinnern, dass die Absicht der Methode darin besteht, eine übergeordnete Methode zu überschreiben. Als Beispiel:

protected boolean displaySensitiveInformation() {
  return false;
}

Sie werden häufig so etwas wie die obige Methode sehen, die eine Methode in der Basisklasse überschreibt. Dies ist ein wichtiges Implementierungsdetail dieser Klasse. Wir möchten nicht, dass vertrauliche Informationen angezeigt werden.

Angenommen, diese Methode wird in der übergeordneten Klasse in geändert

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

Diese Änderung verursacht keine Fehler oder Warnungen bei der Kompilierung, ändert jedoch das beabsichtigte Verhalten der Unterklasse vollständig.

Um Ihre Frage zu beantworten: Sie sollten die Annotation @Override verwenden, wenn das Fehlen einer Methode mit derselben Signatur in einer Oberklasse auf einen Fehler hinweist.


46

Hier gibt es viele gute Antworten, also lassen Sie mich eine andere Sichtweise anbieten ...

Es gibt keinen Overkill, wenn Sie codieren. Die Eingabe von @override kostet Sie nichts, aber die Einsparungen können immens sein, wenn Sie einen Methodennamen falsch geschrieben oder die Signatur leicht falsch geschrieben haben.

Stellen Sie sich das so vor: In der Zeit, in der Sie hier navigiert und diesen Beitrag getippt haben, haben Sie so ziemlich mehr Zeit verbraucht, als Sie für den Rest Ihres Lebens mit @override verbringen werden. Ein Fehler, den es verhindert, kann Ihnen Stunden sparen.

Java unternimmt alles, um sicherzustellen, dass Sie beim Bearbeiten / Kompilieren keine Fehler gemacht haben. Dies ist eine praktisch kostenlose Möglichkeit, eine ganze Klasse von Fehlern zu lösen, die außerhalb umfassender Tests auf keine andere Weise vermeidbar sind.

Könnten Sie einen besseren Mechanismus in Java finden, um sicherzustellen, dass der Benutzer, der eine Methode überschreiben wollte, dies tatsächlich tat?

Ein weiterer netter Effekt ist, dass Sie beim Kompilieren gewarnt werden, wenn Sie die Annotation nicht angeben, dass Sie versehentlich eine übergeordnete Methode überschrieben haben - etwas, das von Bedeutung sein kann, wenn Sie dies nicht beabsichtigen.


3
"Es gibt keinen Overkill, wenn Sie codieren." Ich stimme dem zu, weshalb ich dynamische langs so falsch finde (obwohl 100% meiner bezahlten Arbeit gerade in Rubin ist).
Dan Rosenstark

4
+1: Ich hatte möglicherweise 10 Fehler, die durch einen Fehler beim Überschreiben verursacht wurden. Die Zeit, die erforderlich war, um einen von ihnen zu finden, hätte die Zeit für die Eingabe von @Override bei jeder meiner überschreibenden Methoden leicht überschritten. Außerdem, wenn @Override etwas belastend ist, verwenden Sie wahrscheinlich die Vererbung übermäßig.
Lawrence Dol

7
Ein sehr realer Nachteil ist, dass Sie das Lesen des Codes erschweren, indem Sie ihn mit Schnecken verunreinigen. Vielleicht ist dies ein Fehler meiner IDE, aber ich habe dies selbst erlebt.
Behandle deine Mods gut am

9
@phyzome Wenn Sie die "Schnecken" als umständlich empfinden, verwenden Sie NIEMALS in der Nähe von genügend Kommentaren. Sie sollten nur eine einzelne Zeile über Ihrem Methodenkopf sein, die in den meisten Fällen ungefähr so ​​groß sein sollte wie Ihre Methode (einige Zeilen), um anständigen Schwebetext und Javadocs bereitzustellen. Ich denke, ich sage, dass das Problem nicht die Schnecken sind, sondern Ihre Lesegewohnheiten. Stören Sie all diese Klammern im Code auch?
Bill K

4
Ja, die Codierung ist übertrieben: Wenn Sie Kommentare schreiben, die nur nachahmen, was der Code offensichtlich tut.
Ameisen

22

Ich benutze immer das Tag. Es ist ein einfaches Flag zur Kompilierungszeit, um kleine Fehler zu erkennen, die ich machen könnte.

Es wird Dinge wie tostring()statt fangentoString()

Die kleinen Dinge helfen bei großen Projekten.


18

Die Verwendung der @OverrideAnmerkung dient als Schutz zur Kompilierungszeit vor einem häufigen Programmierfehler. Es wird ein Kompilierungsfehler ausgegeben, wenn Sie die Annotation zu einer Methode haben, bei der Sie die Superklassenmethode nicht tatsächlich überschreiben.

Dies ist am häufigsten der Fall, wenn Sie eine Methode in der Basisklasse so ändern, dass sie eine andere Parameterliste enthält. Eine Methode in einer Unterklasse, die zum Überschreiben der Oberklassenmethode verwendet wurde, tut dies aufgrund der geänderten Methodensignatur nicht mehr. Dies kann manchmal zu seltsamem und unerwartetem Verhalten führen, insbesondere beim Umgang mit komplexen Vererbungsstrukturen. Die @OverrideAnnotation schützt dagegen.


Beste Antwort. Kurz und bündig. Ich wünschte, Sie könnten erklären, wie der "Schutz" funktioniert ... niemand hat dies erklärt.
Djangofan

Es ist einfach zu erklären. Wenn Sie einen Fehler machen (entweder durch Ändern der Schnittstelle, der abstrakten Klasse oder der Unterklasse), erhalten Sie entweder eine Warnung (z. B. in Eclipse) oder einen Fehler beim Kompilieren, der Sie darüber informiert, dass Ihr @Override nicht funktioniert. Der eigentliche Fehler Die Nachricht hängt davon ab, was geändert wurde, aber in Eclipse (zum Beispiel) ist sehr schnell klar, dass es ein Problem gibt: Sie werden sehen, dass der kleine rote Zickzack unterstrichen ist, und ein Mauszeiger über den beleidigenden Text zeigt Ihnen, was falsch ist. Ich nenne das guten Wert.
Ichiro Furusato

14

Um die Compilerprüfung zu nutzen, sollten Sie immer die Annotation überschreiben verwenden. Vergessen Sie jedoch nicht, dass Java Compiler 1.5 diese Annotation beim Überschreiben von Schnittstellenmethoden nicht zulässt. Sie können es nur verwenden, um Klassenmethoden zu überschreiben (abstrakt oder nicht).

Einige IDEs, wie Eclipse, die sogar mit Java 1.6-Laufzeit oder höher konfiguriert sind, behalten die Konformität mit Java 1.5 bei und erlauben nicht die Verwendung von @override wie oben beschrieben. Um dieses Verhalten zu vermeiden, gehen Sie zu: Projekteigenschaften -> Java-Compiler -> Aktivieren Sie "Projektspezifische Einstellungen aktivieren" -> Wählen Sie "Compiler-Konformitätsstufe" = 6.0 oder höher.

Ich verwende diese Annotation gerne jedes Mal, wenn ich eine Methode unabhängig überschreibe, wenn die Basis eine Schnittstelle oder Klasse ist.

Auf diese Weise können Sie einige typische Fehler vermeiden, z. B. wenn Sie glauben, dass Sie einen Ereignishandler überschreiben und dann nichts passiert. Stellen Sie sich vor, Sie möchten einer UI-Komponente einen Ereignis-Listener hinzufügen:

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

Der obige Code wird kompiliert und ausgeführt. Wenn Sie jedoch die Maus in eine UIComponent bewegen, wird der Code "etwas tun" die Ausführung notieren, da Sie die Basismethode tatsächlich nicht überschreiben mouseEntered(MouseEvent ev). Sie erstellen einfach eine neue Methode ohne Parameter mouseEntered(). Wenn Sie anstelle dieses Codes die @OverrideAnmerkung verwendet haben, ist ein Kompilierungsfehler aufgetreten, und Sie haben keine Zeit damit verschwendet, darüber nachzudenken, warum Ihr Ereignishandler nicht ausgeführt wurde.


8

@Override zur Schnittstellenimplementierung ist inkonsistent, da es in Java kein "Überschreiben einer Schnittstelle" gibt.

@Override on Interface Implementation ist nutzlos, da es in der Praxis keine Fehler abfängt , die die Kompilierung sowieso nicht abfangen würde. Es gibt nur ein weit hergeholtes Szenario, in dem das Überschreiben von Implementierern tatsächlich etwas bewirkt: Wenn Sie eine Schnittstelle implementieren und die Schnittstellen-REMOVES-Methoden, werden Sie bei der Kompilierung benachrichtigt, dass Sie die nicht verwendeten Implementierungen entfernen sollten. Beachten Sie, dass, wenn die neue Version der Schnittstelle NEW- oder CHANGED-Methoden enthält, Sie offensichtlich sowieso einen Kompilierungsfehler erhalten, da Sie das neue Material nicht implementieren.

@Override auf Schnittstellenimplementierern sollte in 1.6 niemals erlaubt sein, und da Eclipse sich leider dafür entschieden hat, die Anmerkungen als Standardverhalten automatisch einzufügen, erhalten wir viele überfüllte Quelldateien. Beim Lesen von 1.6-Code können Sie in der Annotation @Override nicht erkennen, ob eine Methode tatsächlich eine Methode in der Oberklasse überschreibt oder nur eine Schnittstelle implementiert.

Die Verwendung von @Override beim tatsächlichen Überschreiben einer Methode in einer Oberklasse ist in Ordnung.


2
Zu diesem Punkt gibt es unterschiedliche Meinungen. Siehe stackoverflow.com/questions/212614/… .
Sleske

8

Es ist am besten, es für jede Methode zu verwenden, die als Überschreibung gedacht ist, und Java 6+, jede Methode, die als Implementierung einer Schnittstelle gedacht ist.

Erstens werden beim Kompilieren Rechtschreibfehler wie " hashcode()" statt " hashCode()" abgefangen. Es kann verwirrend sein, zu debuggen, warum das Ergebnis Ihrer Methode nicht mit Ihrem Code übereinstimmt, wenn die eigentliche Ursache darin besteht, dass Ihr Code niemals aufgerufen wird.

Wenn eine Oberklasse eine Methodensignatur ändert, können Überschreibungen der älteren Signatur "verwaist" werden und als verwirrender toter Code zurückbleiben. Die @OverrideAnmerkung wird Ihnen helfen, diese Waisen zu identifizieren , so dass sie modifiziert werden können , die neue Signatur übereinstimmen.


7

Wenn Sie feststellen, dass Sie sehr oft (nicht abstrakte) Methoden überschreiben, möchten Sie sich wahrscheinlich Ihr Design ansehen. Dies ist sehr nützlich, wenn der Compiler den Fehler sonst nicht abfangen würde. Zum Beispiel habe ich versucht, initValue () in ThreadLocal zu überschreiben, was ich getan habe.

Die Verwendung von @Override bei der Implementierung von Schnittstellenmethoden (Feature 1.6+) scheint mir etwas übertrieben. Wenn Sie eine Menge Methoden haben, von denen einige überschreiben und andere nicht, ist das Design wahrscheinlich wieder schlecht (und Ihr Editor wird wahrscheinlich zeigen, welche welche ist, wenn Sie es nicht wissen).


2
Eigentlich ist es auch schön, Schnittstellenmethoden zu überschreiben. Wenn ich zB eine alte, veraltete Methode von einer Schnittstelle entferne, sollte diese Methode auch aus allen implementierenden Klassen entfernt werden - leicht zu erkennen, wenn sie @override verwenden.
Dominik Sandjaja

7

@Override on Interfaces sind tatsächlich hilfreich, da Sie Warnungen erhalten, wenn Sie die Schnittstelle ändern.


7

Eine andere Sache, die es tut, ist, dass es beim Lesen des Codes offensichtlicher macht, dass es das Verhalten der übergeordneten Klasse ändert. Dann kann beim Debuggen helfen.

In Joshua Blocks Buch Effective Java (2. Auflage) enthält Punkt 36 weitere Einzelheiten zu den Vorteilen der Anmerkung.


Ja, in der Tat - Punkt 36 :)
Chris Kimpton

6

Es macht absolut keinen Sinn, @Override bei der Implementierung einer Schnittstellenmethode zu verwenden. In diesem Fall hat die Verwendung keinen Vorteil - der Compiler erkennt Ihren Fehler bereits, sodass nur unnötige Unordnung entsteht.


6
Wenn Sie @Overrideeine Schnittstelle verwenden, werden Sie gezwungen zu bemerken, wenn eine Methode in der Schnittstelle entfernt wird.
Alex B

@Alex: Das Entfernen von Methoden in einer Schnittstelle ist eine grundlegende Änderung, wie das Hinzufügen von Methoden. Sobald eine Schnittstelle veröffentlicht wurde, ist sie effektiv gesperrt, es sei denn, Sie haben die vollständige Kontrolle über den gesamten Code, der sie verwendet.
Lawrence Dol

6

Immer wenn eine Methode eine andere Methode überschreibt oder eine Methode eine Signatur in einer Schnittstelle implementiert.

Die @OverrideAnmerkung versichert Ihnen, dass Sie tatsächlich etwas überschrieben haben. Ohne die Anmerkung riskieren Sie einen Rechtschreibfehler oder einen Unterschied in Parametertypen und -nummer.


1
Sie können es nur verwenden, um die Implementierung der Schnittstelle in Java 1.6 zu markieren
Dave L.

5

Ich benutze es jedes Mal. Es sind weitere Informationen, mit denen ich schnell herausfinden kann, was los ist, wenn ich den Code in einem Jahr erneut besuche und vergessen habe, was ich beim ersten Mal gedacht habe.


5

Am besten verwenden Sie es immer (oder lassen Sie es von der IDE für Sie ausfüllen).

@Override ist nützlich, um Änderungen in übergeordneten Klassen zu erkennen, die in der Hierarchie nicht gemeldet wurden. Ohne sie können Sie eine Methodensignatur ändern und vergessen, ihre Überschreibungen zu ändern. Mit @Override fängt der Compiler sie für Sie ab.

Diese Art von Sicherheitsnetz ist immer gut zu haben.


1
Wenn Sie also die übergeordnete Methode ändern und @Override nicht in der Methode der untergeordneten Klasse verwenden, sagt die Kompilierung dann etwas aus oder bleibt stumm? Gibt Ihnen die Verwendung von "Override" weitere Informationen, und wenn ja, welche?
Djangofan

5

Ich benutze es überall. Beim Thema des Aufwands für Markierungsmethoden lasse ich Eclipse dies für mich tun, es ist also kein zusätzlicher Aufwand.

Ich bin religiös in Bezug auf kontinuierliches Refactoring ... also werde ich alles tun, um es reibungsloser zu machen.


5
  • Wird nur für Methodendeklarationen verwendet.
  • Gibt an, dass die mit Anmerkungen versehene Methodendeklaration eine Deklaration im Supertyp überschreibt.

Bei konsequenter Anwendung schützt es Sie vor einer großen Klasse schändlicher Fehler.

Verwenden Sie die Annotation @Override, um diese Fehler zu vermeiden: (Erkennen Sie den Fehler im folgenden Code :)

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());
    }
}

Quelle: Effektives Java


Ich weiß nicht, wie die Vorrangregeln für Operatoren in Java lauten, aber Ihre Equals-Methode schreit BUUUUUUUUUUG! Ich würde schreiben (b.first == first) && (b.second == second), selbst wenn ich &&eine niedrigere Priorität hätte als ==.
Pyon

Wussten Sie, dass auf Ihrem Link die Meldung "Sie müssen sich anmelden" angezeigt wird, die den nützlichen Teil dieser Seite abdeckt?
Adriano Varoli Piazza

@Adriano: Sorry Alter !! Bin hilflos !! Als ich die 'Antwort' schrieb, war sie verfügbar. Keine Sorge ... kaufe das Buch. Es lohnt sich, es zu haben !!
Jai

5
Die Methode equals überschreibt nicht: Das Original Object::equalsist boolean equals(Object), während die überschriebene equalsist boolean equals(Bigram), die eine andere Methode Signatur hat, die nicht überschrieben. Durch Hinzufügen von @Override zum equalswird dieser Fehler erkannt .
Ming-Tang

3

Seien Sie vorsichtig, wenn Sie Override verwenden, da Sie danach in starUML kein Reverse Engineering durchführen können. mach zuerst das uml.


2

Es scheint, dass sich die Weisheit hier ändert. Heute habe ich IntelliJ IDEA 9 installiert und festgestellt, dass die " fehlende @ Override-Inspektion " jetzt nicht nur implementierte abstrakte Methoden, sondern auch implementierte Schnittstellenmethoden erfasst . In der Codebasis meines Arbeitgebers und in meinen eigenen Projekten hatte ich lange die Angewohnheit, @Override nur für die zuvor implementierten abstrakten Methoden zu verwenden. Wenn Sie jedoch die Gewohnheit überdenken, wird der Vorteil der Verwendung der Anmerkungen in beiden Fällen deutlich. Obwohl es ausführlicher ist, schützt es vor dem fragilen Problem der Basisklasse (nicht so schwerwiegend wie C ++ - Beispiele), bei dem sich der Name der Schnittstellenmethode ändert, wodurch die potenzielle Implementierungsmethode in einer abgeleiteten Klasse verwaist wird.

Natürlich ist dieses Szenario meistens eine Übertreibung. Die abgeleitete Klasse würde nicht mehr kompiliert werden, da jetzt keine Implementierung der umbenannten Schnittstellenmethode mehr vorhanden ist, und heute würde man wahrscheinlich eine Refactoring-Operation zur Umbenennungsmethode verwenden, um die gesamte Codebasis massenhaft zu adressieren.

Da die Inspektion von IDEA nicht so konfiguriert werden kann, dass implementierte Schnittstellenmethoden ignoriert werden, werde ich heute sowohl meine Gewohnheit als auch die Codeüberprüfungskriterien meines Teams ändern.


2

Die Annotation @Override wird verwendet, um zu überprüfen, ob der Entwickler die richtige Methode in der übergeordneten Klasse oder Schnittstelle überschreiben soll. Wenn sich der Name der Methoden von super ändert, kann der Compiler diesen Fall benachrichtigen, nur um die Konsistenz mit der Super- und der Unterklasse zu gewährleisten.

Übrigens, wenn wir die Annotation @Override in der Unterklasse nicht angekündigt haben, aber einige Methoden des Super überschreiben, kann die Funktion mit dem @Override wie diese funktionieren. Diese Methode kann den Entwickler jedoch nicht benachrichtigen, wenn die Methode des Super geändert wurde. Weil es den Zweck des Entwicklers nicht kannte - die Methode von super überschreiben oder eine neue Methode definieren?

Wenn wir diese Methode überschreiben möchten, um den Polymorphismus zu nutzen, sollten wir @Override über der Methode hinzufügen.


1

Ich benutze es so oft wie möglich, um festzustellen, wann eine Methode überschrieben wird. Wenn Sie sich die Programmiersprache Scala ansehen, haben sie auch ein Überschreibungsschlüsselwort. Ich finde es nützlich.


0

Sie (der Compiler) können damit abfangen, wenn Sie für einen Methodennamen, den Sie überschreiben, die falsche Schreibweise verwendet haben.


0

Die Annotation zum Überschreiben wird verwendet, um den Compiler zu nutzen und zu überprüfen, ob Sie tatsächlich eine Methode aus der übergeordneten Klasse überschreiben. Es wird verwendet, um zu benachrichtigen, wenn Sie einen Fehler machen, z. B. einen Fehler bei der Rechtschreibung eines Methodennamens oder einen Fehler bei der nicht korrekten Übereinstimmung mit den Parametern


0

Ich denke, es ist am besten, die @override zu codieren, wann immer dies erlaubt ist. es hilft bei der Codierung. Beachten Sie jedoch, dass für ecipse Helios, entweder SDK 5 oder 6, die Annotation @override für implementierte Schnittstellenmethoden zulässig ist. Bei Galileo (5 oder 6) ist die Annotation @override nicht zulässig.


0

Annotationen stellen dem Compiler Metadaten über den Code zur Verfügung, und die Annotation @Override wird im Falle einer Vererbung verwendet, wenn eine Methode der Basisklasse überschrieben wird. Es teilt dem Compiler lediglich mit, dass Sie die Methode überschreiben. Es kann einige häufige Fehler vermeiden, die wir tun können, wenn wir nicht der richtigen Signatur der Methode folgen oder den Namen der Methode falsch schreiben usw. Daher ist es eine gute Praxis, die @ Override-Annotation zu verwenden.


0

Für mich stellt der @Override sicher, dass ich die Signatur der Methode korrekt habe. Wenn ich die Anmerkung eingebe und die Methode nicht richtig geschrieben ist, beschwert sich der Compiler und lässt mich wissen, dass etwas nicht stimmt.


0

Einfach - Wenn Sie eine in Ihrer Oberklasse vorhandene Methode überschreiben möchten, verwenden Sie @OverrideAnnotation, um eine korrekte Überschreibung vorzunehmen. Der Compiler warnt Sie, wenn Sie ihn nicht richtig überschreiben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.