Warum, wenn die statische Methode nicht in Polymorphismus (späte Bindung) involviert ist, sehe ich Fehler, dass die statische Methode nicht überschrieben werden kann

8

Bitte beachten Sie folgenden Code:

%Vor%

Ausgabe:

  

java: m (java.lang.Number) in vererbungTest.B kann nicht überschrieben werden   m (java.lang.Number) in vererbungTest.A Rückgabetyp int ist nicht   kompatibel mit void

Ich weiß, dass statische Methoden keinen Polymorphismus beinhalten, daher folge ich, dass das Überschreiben für meinen Code unmöglich ist. Diese Compiler-Nachricht ist für mich seltsam.

Wie ich verstehe, ist das Überschreiben Teil des Polymorphismus. Ich bereite mich auf scjp vor und ich habe Angst, Fehler in der vertrauten Frage zu machen.

Bitte klären Sie dieses Problem.

erwartetes Verhalten für mich - Meldung über Überladungsfehler

P.S1.

Ich habe die populärste Frage über statisches Overridden gelesen und habe keine Antwort gefunden (

P.S2. Laut Psdemo antworten:

dieser Code:

%Vor%

Ausgänge:

%Vor%

Für mich sind diese Situationen gleich. Aber Compilerfehler ist anders - seltsam.

    
gstackoverflow 09.05.2014, 20:49
quelle

3 Antworten

7

JLS §8.4.8.3 (Java 8) sagt:

  

Wenn eine Methodendeklaration d 1 mit dem Rückgabetyp R <1> die Deklaration einer anderen Methode d <2> überschreibt oder verbirgt sub> mit dem Rückgabetyp R 2, dann muss d 1 & ndash; Rückkehrtyp-ersetzbar sein (§ 8.4.5) für d 2 oder & ohgr ;. Ein Kompilierungsfehler tritt auf.

Diese Regel gilt sowohl für Instanzmethoden als auch für statische Methoden, da sie "überschreibt oder versteckt" lautet. Wenn Sie eine Methode mit demselben Namen und denselben Parametern verwenden, überschreibt sie im Prinzip, ob es sich um eine Instanzmethode handelt, blendet aber (die geerbte Methode) aus, wenn es sich um eine Klassenmethode (statische Methode) handelt. In beiden Fällen muss der Rückgabetyp identisch sein oder den Regeln für die Kovarianz entsprechen.

Da es die gleiche Regel ist, gibt es wahrscheinlich nur einen Platz im Compiler-Code, der diese Regel überprüft, und wenn die Regel verletzt wird, erhalten Sie den Fehler, den Sie sehen, was sicherlich viel mehr ist gewöhnliches Vorkommnis. Der Compiler sollte wirklich überprüfen, ob es "overrides" oder "hides" sagen soll, aber es sieht so aus, als wären sie ausgerutscht. Die genau richtige Fehlermeldung ist normalerweise nicht die höchste Priorität von Compiler-Schreibern - nicht im Vergleich dazu, dass Code, der kompiliert werden soll, dies tut und richtig läuft, und Code, der nicht kompiliert werden soll, nicht. Also ich denke, das ist ein Mangel, aber ein sehr kleiner.

    
ajb 09.05.2014, 21:12
quelle
7

Auch wenn statische Methoden nicht überschrieben werden können, werden sie immer noch vererbt. Was Sie also versuchen, würde zu einer ähnlichen Situation führen wie

%Vor%

Das ist falsch, weil Sie nicht zwei Methoden mit derselben Signatur, aber mit unterschiedlichen Rückgabetypen haben können. Der Grund, warum es verboten war, ist ganz einfach: Der Compiler könnte nicht entscheiden, welche Methode Foo method() Bar method() Sie beispielsweise in Situationen wie

aufrufen möchten %Vor%

Um diese Art von Situationen zu verhindern, verbietet der Compiler das Überschreiben / Verbergen von Methoden mit derselben Signatur, indem die Rückgabetypen geändert werden. Einzige Ausnahme ist, wenn Sie den Rückgabetyp zu einem detaillierteren wie

ändern %Vor%

So scheint es, dass override hier nicht das beste Wort ist. Korrektes Wort sollte hide sein, da statische Methoden versteckt, nicht überschrieben werden können, aber da es die gleiche Regel ist, um nach überschriebenen / versteckten Methoden zu suchen, ist die Fehlermeldung allgemeiner.

    
Pshemo 09.05.2014 20:58
quelle
2

Ich denke, die Compilerfehlerverwendung von 'override' ist hier irreführend, es ist nicht anwendbar.

Die Sprachspezifikation lautet:

  

Wenn eine Methodendeklaration d1 mit dem Rückgabetyp R1 die Deklaration einer anderen Methode d2 mit dem Rückgabetyp R2 überschreibt oder verbirgt, muss d1 für d2 den Substitutionstyp für den Rückgabetyp ersetzen oder es tritt ein Kompilierungsfehler auf.

Hier versteckt sich Ihre B-Methode Erklärung von Am:

  

Wenn eine Klasse eine statische Methode m deklariert, dann soll die Deklaration m jede Methode m 'verbergen, wobei die Signatur von m eine Untersignatur (§ 8.4.2) der Signatur von m' in den Oberklassen und ist Superschnittstellen der Klasse, auf die ansonsten in der Klasse zugegriffen werden könnte.

Wenn Ihre B-Klasse keine m-Methode hat, dann könnten Sie B.m aufrufen und es würde das auf A definierte m aufrufen.

Mit B.m wird A's Version von m versteckt. Da Sie eine statische Methode aufrufen können, die für eine Oberklasse definiert ist, aber auf die Unterklasse verweist, werden einige Erwartungen bezüglich der Methode erzeugt, die durch den unterschiedlichen Rückgabetyp verletzt werden.

Es wird versteckt und nicht überschrieben, denn wenn Sie ein B.m definiert haben, können Sie immer noch A.m aufrufen und die Version der Methode der Oberklasse erhalten. Beim Überschreiben ist es der Laufzeittyp, der entscheidet, was aufgerufen wird und wie es aufgerufen wird, ist egal.

    
Nathan Hughes 09.05.2014 21:33
quelle