Ich bin verwirrt darüber, wie sich das Überschreiben vom Verstecken in Java unterscheidet. Kann jemand mehr Details darüber geben, wie sich diese unterscheiden? Ich habe das Java-Tutorial gelesen, aber der Beispielcode hat mich immer noch verwirrt.
Um es klarer zu machen, verstehe ich das Überschreiben gut. Mein Problem ist, dass ich nicht sehe, wie sich das Verstecken unterscheidet, außer dass sich eines auf Instanzebene befindet, während sich das andere auf Klassenebene befindet.
Betrachten Sie den Java-Tutorial-Code:
public class Animal {
public static void testClassMethod() {
System.out.println("Class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("Instance " + " method in Animal.");
}
}
Dann haben wir eine Unterklasse Cat
:
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
Dann sagen sie:
Die Ausgabe dieses Programms lautet wie folgt:
Klassenmethode in Tier.
Die Instanzmethode in Cat.
Für mich ist die Tatsache, dass das Aufrufen einer Klassenmethode testClassMethod()
direkt von der Animal
Klasse aus die Methode in der Klasse ausführt, Animal
ziemlich offensichtlich, nichts Besonderes. Dann rufen sie das testInstanceMethod()
von einem Verweis auf auf myCat
, was wiederum ziemlich offensichtlich ist, dass die dann ausgeführte Methode diejenige in der Instanz von ist Cat
.
Soweit ich weiß, verhält sich das Ausblenden von Anrufen wie das Überschreiben. Warum also diese Unterscheidung treffen? Wenn ich diesen Code mit den oben genannten Klassen ausführe:
Cat.testClassMethod();
Ich werde bekommen:
Die Klassenmethode in Cat.
Aber wenn ich das testClassMethod()
von Cat entferne , bekomme ich:
Die Klassenmethode in Animal.
Was mir zeigt, dass das Schreiben einer statischen Methode mit derselben Signatur wie im übergeordneten Element in einer Unterklasse so ziemlich eine Überschreibung bewirkt.
Hoffentlich mache ich klar, wo ich verwirrt bin und jemand kann etwas Licht ins Dunkel bringen. Vielen Dank im Voraus!
quelle
Antworten:
Das Überschreiben unterstützt grundsätzlich die späte Bindung. Daher wird zur Laufzeit entschieden, welche Methode aufgerufen wird. Es ist für nicht statische Methoden.
Das Ausblenden gilt für alle anderen Mitglieder (statische Methoden, Instanzmitglieder, statische Mitglieder). Es basiert auf der frühen Bindung. Genauer gesagt wird die Methode oder das Mitglied, das aufgerufen oder verwendet werden soll, während der Kompilierungszeit festgelegt.
In Ihrem Beispiel ist der erste Aufruf
Animal.testClassMethod()
ein Aufruf einerstatic
Methode, daher ist es ziemlich sicher, welche Methode aufgerufen wird.Im zweiten Aufruf rufen
myAnimal.testInstanceMethod()
Sie eine nicht statische Methode auf. Dies nennen Sie Laufzeitpolymorphismus. Erst zur Laufzeit wird entschieden, welche Methode aufgerufen werden soll.Weitere Informationen finden Sie unter Überschreiben gegen Verstecken .
quelle
private methods
? Sie können es nicht sein,overridden
da die Unterklasse nichts über ihre Existenz weiß. Deshalb könnten sie eshidden
stattdessen sein.Statische Methoden werden ausgeblendet, nicht statische Methoden werden überschrieben. Der Unterschied ist bemerkenswert, wenn Aufrufe nicht als "etwas ()" oder "this.something ()" qualifiziert sind.
Ich kann es nicht wirklich auf Worte fassen, also hier ein Beispiel:
AUSGABE:
quelle
husky.Animal();
wird es animal.something oder dog.something drucken ? Ich denke, es ist FALSCH zu sagen, dass dies immer Animal.something ()Dies ist der Unterschied zwischen Überschreibungen und Verstecken.
quelle
Wenn ich Ihre Frage richtig verstehe, lautet die Antwort "Sie überschreiben bereits".
"Was mir zeigt, dass das Schreiben einer statischen Methode mit demselben Namen wie im übergeordneten Element in einer Unterklasse so ziemlich eine Überschreibung bewirkt."
Wenn Sie eine Methode in eine Unterklasse mit genau demselben Namen wie eine Methode in einer Oberklasse schreiben, wird die Methode der Oberklasse überschrieben. Die Annotation @Override ist nicht erforderlich, um eine Methode zu überschreiben. Dies macht Ihren Code jedoch lesbarer und zwingt den Compiler zu überprüfen, ob Sie tatsächlich eine Methode überschreiben (und beispielsweise die Unterklassenmethode nicht falsch geschrieben haben).
quelle
Das Überschreiben erfolgt nur mit Instanzmethoden. Wenn der Typ der Referenzvariablen Animal und das Objekt Cat ist, wird die Instanzmethode von Cat aufgerufen (dies wird überschrieben). Für dasselbe acat-Objekt wird die Klassenmethode Animal verwendet.
Ausgabe ist:
quelle
Die Regel zum Speichern ist einfach: Eine Methode in einer erweiterten Klasse kann statisch nicht in void und void nicht in statisch ändern. Dies führt zu Kompilierungsfehlern.
Aber wenn
void Name
geändert wird, istvoid Name
es Overriding.Und wenn
static Name
geändert wird, iststatic Name
es Verstecken. (Je nach Art der Referenz, die zum Aufrufen der Methode verwendet wird, können sowohl die statische Methode der Unterklasse als auch die der Oberklasse aufgerufen werden.)quelle
In diesem Codeausschnitt verwende ich den Zugriffsmodifikator "privat" anstelle von "statisch", um Ihnen den Unterschied zwischen ausgeblendeten und überschreibenden Methoden zu zeigen.
Ausgabe:
quelle
Basierend auf meinen letzten Java-Studien
Beispiel aus dem OCP Java 7-Buch, Seite 70-71:
aber wenn wir folgendes schreiben:
Im zweiten Hauptteil verwenden wir die Object-Klasse als statischen Typ. Wenn wir also die Equal-Methode im Point-Objekt aufrufen, wartet eine Point-Klasse darauf, als Parameter anzukommen, aber das Objekt kommt. Die Object-Klasse entspricht also der Methode, die ausgeführt wird, da wir dort ein Equals (Object o) haben. In diesem Fall überschreibt die Klasse des Punkts gleich nicht, sondern verbirgt die Methode Objektklasse gleich .
quelle
quelle
Die verknüpfte Java-Tutorial-Seite erklärt das Konzept des Überschreibens und Versteckens
Die Unterscheidung zwischen dem Ausblenden einer statischen Methode und dem Überschreiben einer Instanzmethode hat wichtige Auswirkungen:
Zurück zu Ihrem Beispiel:
Die obige Aussage zeigt noch kein Verstecken.
Ändern Sie nun den Code wie folgt, um eine andere Ausgabe zu erhalten:
quelle
Zusätzlich zu den oben aufgeführten Beispielen finden Sie hier einen kleinen Beispielcode, um die Unterscheidung zwischen Ausblenden und Überschreiben zu verdeutlichen:
Der Aufruf von
child.printParent()
Ausgaben:versteckt werden: Eltern
überschrieben werden: Kind
Der Aufruf der
child.printChild()
Ausgaben:versteckt werden: Kind
überschrieben werden: Kind
Wie aus den obigen Ausgaben (insbesondere den fett markierten Ausgaben) hervorgeht, verhält sich das Ausblenden von Methoden anders als das Überschreiben.
Java erlaubt das Ausblenden und Überschreiben nur für Methoden. Die gleiche Regel gilt nicht für Variablen. Das Überschreiben von Variablen ist nicht zulässig, daher können Variablen nur ausgeblendet werden (kein Unterschied zwischen statischen und nicht statischen Variablen). Das folgende Beispiel zeigt, wie die Methode
getName()
überschrieben und die Variablename
ausgeblendet wird:quelle
Zur Laufzeit wird die untergeordnete Version einer überschriebenen Methode immer für eine Instanz ausgeführt, unabhängig davon, ob der Methodenaufruf in einer übergeordneten oder untergeordneten Klassenmethode definiert ist. Auf diese Weise wird die übergeordnete Methode nur verwendet, wenn auf einen expliziten Aufruf der übergeordneten Methode unter Verwendung der Syntax ParentClassName.method () verwiesen wird. Alternativ wird zur Laufzeit die übergeordnete Version einer versteckten Methode immer ausgeführt, wenn der Aufruf der Methode in der übergeordneten Klasse definiert ist.
quelle
Beim Überschreiben von Methoden erfolgt die Methodenauflösung durch die JVM auf der Grundlage des Laufzeitobjekts. Während beim Ausblenden von Methoden die Methodenauflösung vom Compiler auf der Grundlage von Referenzen vorgenommen wird. So,
Wenn der Code geschrieben worden wäre als,
Die Ausgabe wäre wie folgt:
Klassenmethode in Tier.
quelle
Es wird als Ausblenden bezeichnet, da der Compiler die Implementierung der Superklassenmethode verbirgt, wenn die Unterklasse dieselbe statische Methode hat.
Der Compiler hat keine eingeschränkte Sichtbarkeit für überschriebene Methoden und nur zur Laufzeit wird entschieden, welche verwendet wird.
quelle
Dies ist der Unterschied zwischen Überschreiben und Verstecken:
Tier a = neue Katze ();
a.testClassMethod () ruft die Methode in der übergeordneten Klasse auf, da dies ein Beispiel für das Ausblenden von Methoden ist. Die aufzurufende Methode wird durch den Typ der Referenzvariablen bestimmt und zur Kompilierungszeit festgelegt.
a.testInstanceMethod () ruft die Methode in der untergeordneten Klasse auf, da dies ein Beispiel für das Überschreiben von Methoden ist. Die aufzurufende Methode wird durch das Objekt bestimmt, mit dem die Methode zur Laufzeit aufgerufen wird.
quelle
Wie geschieht das Verstecken statischer Methoden in Java? Die Katzenklasse erweitert die Tierklasse. In der Cat-Klasse gibt es also beide statischen Methoden (ich meine die statische Methode der Child-Klasse und die statische Methode der Parent-Klasse). Aber wie versteckt JVM die statische Parent-Methode? Wie geht es mit Heap and Stack?
quelle