Ich mache gerade eine Aufgabe für eine meiner Klassen und muss darin Beispiele für die statische und dynamische Bindung unter Verwendung der Java-Syntax geben .
Ich verstehe das Grundkonzept, dass statische Bindung zur Kompilierungszeit und dynamische Bindung zur Laufzeit erfolgt, aber ich kann nicht herausfinden, wie sie tatsächlich spezifisch funktionieren.
Ich habe online ein Beispiel für statische Bindung gefunden, das dieses Beispiel enthält:
public static void callEat(Animal animal) {
System.out.println("Animal is eating");
}
public static void callEat(Dog dog) {
System.out.println("Dog is eating");
}
public static void main(String args[])
{
Animal a = new Dog();
callEat(a);
}
Und dass dies "Tier frisst" drucken würde, weil der Aufruf zur callEat
Verwendung der statischen Bindung lautet , aber ich bin mir nicht sicher, warum dies als statische Bindung angesehen wird.
Bisher hat es keine der Quellen, die ich gesehen habe, geschafft, dies auf eine Weise zu erklären, der ich folgen kann.
quelle
Antworten:
Aus dem Javarevisited Blog Post :
quelle
Das Verbinden eines Methodenaufrufs mit dem Methodenkörper wird als Bindung bezeichnet. Wie Maulik sagte "Die statische Bindung verwendet Typinformationen (Klasse in Java) für die Bindung, während die dynamische Bindung Object verwendet, um die Bindung aufzulösen." Also dieser Code:
Wird das Ergebnis erzeugen: Hund frisst ... weil er die Objektreferenz verwendet, um herauszufinden, welche Methode verwendet werden soll. Wenn wir den obigen Code in diesen ändern:
Es wird erzeugt: Tier isst ... weil es eine statische Methode ist, also verwendet es Type (in diesem Fall Animal), um zu entscheiden, welche statische Methode aufgerufen werden soll. Neben statischen Methoden verwenden private und endgültige Methoden denselben Ansatz.
quelle
a
es sich tatsächlich um eineDog
Kompilierungszeit handelt?Der Compiler weiß nur, dass der Typ "a" ist
Animal
; Dies geschieht zur Kompilierungszeit, weshalb es als statische Bindung bezeichnet wird (Methodenüberladung). Wenn es sich jedoch um eine dynamische Bindung handelt, wird dieDog
Klassenmethode aufgerufen . Hier ist ein Beispiel für eine dynamische Bindung.Ausgabe: Innenfressmethode des Hundes
quelle
Nun, um zu verstehen, wie statische und dynamische Bindung tatsächlich funktioniert? oder wie werden sie von Compiler und JVM identifiziert?
Nehmen wir das folgende Beispiel, in dem
Mammal
eine übergeordnete Klasse mit einer Methodespeak()
und einer erweitertenHuman
KlasseMammal
diespeak()
Methode überschreibt und sie dann erneut überlädtspeak(String language)
.Wenn wir den obigen Code kompilieren und versuchen, den Bytecode mit zu betrachten
javap -verbose OverridingInternalExample
, können wir sehen, dass der Compiler eine konstante Tabelle generiert, in der er jedem Methodenaufruf und Bytecode für das Programm, das ich extrahiert und in das Programm selbst aufgenommen habe, Ganzzahlcodes zuweist ( siehe die Kommentare unter jedem Methodenaufruf)Mit Blick auf obigem Code können wir , dass die Bytecodes sehen
humanMammal.speak()
,human.speak()
undhuman.speak("Hindi")
sind völlig anders (invokevirtual #4
,invokevirtual #7
,invokevirtual #9
) , da der Compiler zwischen ihnen zu unterscheiden , ist in der Lage , basierend auf der Liste der Argumente und Klassenreferenz. Da all dies zur Kompilierungszeit statisch gelöst wird, wird das Überladen von Methoden als statischer Polymorphismus oder statische Bindung bezeichnet .Aber Bytecode für
anyMammal.speak()
undhumanMammal.speak()
ist gleich (invokevirtual #4
), da laut Compiler beide Methoden aufgerufen werdenMammal
Referenz .Nun stellt sich die Frage, ob beide Methodenaufrufe denselben Bytecode haben. Woher weiß JVM dann, welche Methode aufgerufen werden soll?
Nun, die Antwort ist im Bytecode selbst versteckt und es handelt sich um einen
invokevirtual
Befehlssatz. JVM verwendet dieinvokevirtual
Anweisung, um ein Java-Äquivalent der virtuellen C ++ - Methoden aufzurufen. Wenn wir in C ++ eine Methode in einer anderen Klasse überschreiben möchten, müssen wir sie als virtuell deklarieren. In Java sind jedoch alle Methoden standardmäßig virtuell, da wir jede Methode in der untergeordneten Klasse überschreiben können (außer privaten, endgültigen und statischen Methoden).In Java enthält jede Referenzvariable zwei versteckte Zeiger
Alle Objektreferenzen enthalten also indirekt eine Referenz auf eine Tabelle, die alle Methodenreferenzen dieses Objekts enthält. Java hat dieses Konzept von C ++ ausgeliehen und diese Tabelle wird als virtuelle Tabelle (vtable) bezeichnet.
Eine vtable ist eine Array-ähnliche Struktur, die virtuelle Methodennamen und deren Referenzen auf Array-Indizes enthält. JVM erstellt nur eine vtable pro Klasse, wenn die Klasse in den Speicher geladen wird.
Wenn JVM also auf einen
invokevirtual
Befehlssatz stößt , überprüft es die vtable dieser Klasse auf die Methodenreferenz und ruft die spezifische Methode auf, die in unserem Fall die Methode eines Objekts ist, nicht die Referenz.Da all dies nur zur Laufzeit gelöst wird und JVM zur Laufzeit erfährt, welche Methode aufgerufen werden muss, wird das Überschreiben von Methoden als dynamischer Polymorphismus oder einfach als Polymorphismus oder dynamische Bindung bezeichnet .
Sie können es mehr Details zu meinem Artikel lesen Wie funktioniert JVM Handle Methode Overloading und Übergeordnete Intern .
quelle
Es gibt drei Hauptunterschiede zwischen statischer und dynamischer Bindung beim Entwerfen der Compiler und wie Variablen und Prozeduren in die Laufzeitumgebung übertragen werden. Diese Unterschiede sind wie folgt:
Statische Bindung : Bei der statischen Bindung werden drei folgende Probleme diskutiert:
Definition eines Verfahrens
Angabe eines Namens (Variable usw.)
Geltungsbereich der Erklärung
Dynamische Bindung : Drei Probleme, die bei der dynamischen Bindung auftreten, sind folgende:
Aktivierung eines Verfahrens
Bindung eines Namens
Lebensdauer einer Bindung
quelle
Mit der statischen Methode in der übergeordneten und untergeordneten Klasse: Statische Bindung
Dynamische Bindung :
quelle
Alle Antworten hier sind richtig, aber ich möchte etwas hinzufügen, das fehlt. Wenn Sie eine statische Methode überschreiben, wird sie anscheinend überschrieben, aber tatsächlich wird keine Methode überschrieben. Stattdessen wird es als Methodenverstecken bezeichnet. Statische Methoden können in Java nicht überschrieben werden.
Schauen Sie sich das folgende Beispiel an:
Bei der dynamischen Bindung wird die Methode abhängig von der Art der Referenz und nicht von der Art des Objekts aufgerufen , das die Referenzvariable enthält. Hier geschieht die statische Bindung, da das Ausblenden der Methode kein dynamischer Polymorphismus ist. Wenn Sie das statische Schlüsselwort vor eat () entfernen und es zu einer nicht statischen Methode machen, zeigt es Ihnen dynamischen Polymorphismus und nicht das Ausblenden von Methoden.
Ich habe den folgenden Link gefunden, um meine Antwort zu unterstützen: https://youtu.be/tNgZpn7AeP0
quelle
Im Fall des statischen Bindungstyps des Objekts, der zur Kompilierungszeit bestimmt wird, während im dynamischen Bindungstyp des Objekts zur Laufzeit bestimmt wird.
quelle
Weil der Compiler die Bindung zur Kompilierungszeit kennt. Wenn Sie beispielsweise eine Methode auf einer Schnittstelle aufrufen, kann der Compiler dies nicht wissen und die Bindung wird zur Laufzeit aufgelöst, da das tatsächliche Objekt, auf dem eine Methode aufgerufen wird, möglicherweise eines von mehreren sein kann. Das ist also Laufzeit oder dynamische Bindung.
Ihr Aufruf ist zur Kompilierungszeit an die Animal-Klasse gebunden, da Sie den Typ angegeben haben. Wenn Sie diese Variable an eine andere Methode übergeben würden, würde niemand (außer Ihnen, weil Sie sie geschrieben haben) wissen, um welche tatsächliche Klasse es sich handelt. Der einzige Hinweis ist der deklarierte Tiertyp.
quelle