Wenn das Programm ausgeführt wird, ist der Methodenaufruf die häufigste und häufigste Operation Welche Methode wird aufgerufen? Der Kompilierungsprozess der Klassendatei umfasst nicht den Verbindungsschritt. Alle Methodenaufrufe werden in der Klassendatei gespeichert in der Klassendatei. Dies sind alles symbolische Referenzen, nicht die Eintragsadresse der Methode im tatsächlichen Laufzeitspeicherlayout, d
Es macht auch Java-Methoden Der Aufrufprozess wird relativ kompliziertDer direkte Verweis auf die Zielmethode muss beim Laden der Klasse oder sogar während der Laufzeit ermittelt werden
Java-Methodenklassifizierung
In Java Es entspricht dem „Kompilierungszeitraum“. Es gibt zwei Hauptkategorien von „laufzeitunveränderlichen“ Methoden:Private Methoden:
Nicht von außen zugänglichNicht-virtuelle Methode:
Während des Unterrichts In der Ladephase wird der Symbolverweis als direkter Verweis auf die Methode aufgelöst Künstliche Methoden:Symbolverweise werden während der Klassenladephase nicht als direkte Verweise auf die Methode aufgelöst
Mit Ausnahme der oben genannten nicht-virtuellen Methoden sind alle anderen Methoden virtuelle Methoden
public class StaticDispatch { static abstract class Human { } static class Man extends Human { } static class Woman extends Human { } public static void sayHello(Human guy) { System.out.println("Hello, Guy!"); } public static void sayHello(Man guy) { System.out.println("Hello, Gentleman!"); } public static void sayHello(woman guy) { System.out.println("Hello, Lady!"); } public static void main(String[] args) { Human man = new Man(); Human women = new Woman(); sayHello(man); sayHello(woman); } }
Human
ist der statische Typ der Variablen
Man
ist der tatsächliche Typ der VariablenSowohl der statische Typ als auch der tatsächliche Typ ändern sich im Programm:
Der statische Typ ändert sich nur, wenn er verwendet wird. Der endgültige statische Typ wird im Compiler nicht geändert
Komm schon
Der Compiler weiß während der Kompilierung nicht, was der tatsächliche Typ eines Objekts ist
Human human = new Man(); sayHello(man); sayHello((Man)man); // 类型转换,静态类型变化,转型后的静态类型一定是Man man = new woman(); // 实际类型变化,实际类型是不确定的 sayHello(man); sayHello((Woman)man); // 类型转换,静态类型变化
Der Compiler verwendet den statischen Typ des Parameters anstelle des tatsächlichen Typs als Grundlage für die Beurteilung während Überladung. Der statische Typ wird während der Kompilierung bestimmt. Sie können wissen:
Alle Versandaktionen, die auf statischen Typen basieren, um die Ausführungsversion der Methode zu finden die virtuelle Maschine, aber vom Compiler vervollständigt
Da das Literal nicht angezeigt wird. Statische Typen können nur durch Sprachregeln verstanden und abgeleitet werdenpublic class LiteralTest { public static void sayHello(char arg) { System.out.println("Hello, char!"); } public static void sayHello(int arg) { System.out.println("Hello, int!"); } public static void sayHello(long arg) { System.out.println("Hello, long!"); } public static void sayHello(Character arg) { System.out.println("Hello, Character!"); } public static void main(String[] arg) { sayHello('a'); } }
sayHello()Wenn die Der Compiler kann nicht bestimmen, an welchen Typ die Konvertierung angepasst werden soll. Es kommt zu einer Typmehrdeutigkeit und die Kompilierung wird verweigert undwoman
rufen die Methode
auf. Es wurden unterschiedliche Verhaltensweisen ausgeführt, als Human
为变量的静态类型
Man
Die Variable man
verschiedene Methoden in zwei Aufrufen ausführteDer Grund für dieses Phänomen
invokevirtual
-AnweisungC
Wenn im Typ C eine Methode gefunden wird, die mit dem Deskriptor und dem einfachen Namen übereinstimmt, wird die Überprüfung der Zugriffsberechtigung durchgeführt. Wenn die Überprüfung erfolgreich ist, wird ein direkter Verweis auf diese Methode zurückgegeben und der Suchvorgang endet schlägt fehl und wirft eine java.lang.illegalAccessErrorException
Wenn es nicht gefunden wird, führen Sie den zweiten Schritt des Such- und Überprüfungsprozesses für jede übergeordnete Klasse vom Typ C von unten nach oben entsprechend der Vererbungsbeziehung durch
Wenn es immer noch nicht gefunden wird. Wenn eine geeignete Methode gefunden wird, wird eine Ausnahme „java.lang.AbstractMethodError“ ausgelöst besteht darin, den tatsächlichen Empfängertyp zur Laufzeit zu bestimmen, sodass die invokevirtual-Anweisung in den beiden Aufrufen die Symbolreferenz der Klassenmethode im Konstantenpool in eine andere direkte Referenz auflöst
Dieser Versandprozess ermittelt die Ausführungsversion der Methode basierend auf dem tatsächlichen Typ Während der Laufzeit wird dynamischer Versand genanntWie verhält sich eine virtuelle Maschine konkret? die entsprechende Zielmethode in den Methodenmetadaten der Klasse zur Laufzeit
Daher führen die meisten Implementierungen bei der tatsächlichen Implementierung virtueller Maschinen aus Leistungsgründen nicht so häufige Suchvorgänge durch
Die am häufigsten verwendete „ Die Methode zur Stabilitätsoptimierung besteht darin, Klassen mit der Erstellung einer virtuellen Methodentabelle (vtable) im Methodenbereich zu versorgen. Verwenden Sie einen virtuellen Methodentabellenindex anstelle einer Metadatensuche, um die Leistung zu verbessern. Die tatsächliche Eintragsadresse jeder Methode wird in der virtuellen Methodentabelle gespeichert:
Wenn eine Methode in der Unterklasse nicht überschrieben wurde, stimmt der Adresseintrag in der virtuellen Methodentabelle der Unterklasse mit dem Adresseintrag derselben Methode in der übergeordneten Klasse überein , und beide verweisen auf den tatsächlichen Eintrag der übergeordneten Klasse
Wenn diese Methode in einer Unterklasse überschrieben wird, wird die Adresse in der Methodentabelle der Unterklasse durch die Eintragsadresse ersetzt, die auf die tatsächliche Methode der Unterklasse zeigt
Methodentabellen werden im Allgemeinen während der Verbindungsphase der Klassenladephase initialisiert: Nachdem die Anfangswerte der Variablen vorbereitet wurden der Klasse initialisiert die virtuelle Maschine auch die Methodentabelle der Klasse
Das obige ist der detaillierte Inhalt vonVerwenden von Java-Methodenaufrufen zum Auflösen von statischem Dispatch und dynamischem Dispatch. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!