Heim  >  Artikel  >  Java  >  Verwenden von Java-Methodenaufrufen zum Auflösen von statischem Dispatch und dynamischem Dispatch

Verwenden von Java-Methodenaufrufen zum Auflösen von statischem Dispatch und dynamischem Dispatch

WBOY
WBOYnach vorne
2023-04-20 23:22:211303Durchsuche

Methodenaufruf

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 kompliziert

Der direkte Verweis auf die Zielmethode muss beim Laden der Klasse oder sogar während der Laufzeit ermittelt werden
  • Methodenanalyse
  • Die Zielmethode in allen Methodenaufrufen ist Das Gleiche gilt für Referenzen auf den konstanten Pool in der Klassendatei

    Während der Lade- und Analysephase der Klasse werden einige der Symbolreferenzen in direkte Referenzen umgewandelt:
Die Methode hat eine bestimmbare Aufrufversion, bevor das Programm tatsächlich ausgeführt wird, und der Aufruf Die Version dieser Methode ist unveränderlich

Das heißt, das Aufrufziel wird im Programmcode vervollständigt und muss beim Kompilieren durch den Compiler ermittelt werden. Dies wird auch als Methodenanalyse bezeichnet

Java-Methodenklassifizierung

In Java Es entspricht dem „Kompilierungszeitraum“. Es gibt zwei Hauptkategorien von „laufzeitunveränderlichen“ Methoden:
  • Statische Methoden:
  • Direkt mit dem Typ verbunden

  • Private Methoden:

    Nicht von außen zugänglich

Die jeweiligen Eigenschaften dieser beiden Methoden Es wird entschieden, dass diese beiden Methoden nicht durch Vererbung oder andere Methoden überschrieben werden können, sodass sie für die Auflösung während der Klassenladephase geeignet sind

Nicht-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

statischer Versand

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 man = new Human() ;
  • Human ist der statische Typ der Variablen

  • Man ist der tatsächliche Typ der Variablen
  • Sowohl der statische Typ als auch der tatsächliche Typ ändern sich im Programm:

Statischer Typ:

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:

  • In der Kompilierungsphase entscheidet der Javac-Compiler basierend auf dem statischen Typ des Parameters, welche überladene Version verwendet werden soll.
  • Statischer Versand:

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 werden

public 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');
	}
}

Der Compiler kommentiert die überladenen Methoden von oben nach unten, um unterschiedliche Ausgaben zu erhalten

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
sayHello()

auf. Es wurden unterschiedliche Verhaltensweisen ausgeführt, als Human为变量的静态类型

Man

Die Variable man

verschiedene Methoden in zwei Aufrufen ausführte

Der Grund für dieses Phänomen
    : Die tatsächlichen Typen davon zwei Variablen sind unterschiedlich
  • Java Virtual So verteilt die Maschine die Ausführungsversion der Methode entsprechend dem tatsächlichen Typ:
  • Ausgehend vom polymorphen Suchprozess der

    invokevirtual

    -Anweisung
  • , dem Laufzeitanalyseprozess der invokevirtual
  • -Anweisung ist grob in die folgenden Schritte unterteilt:

Finden Sie den Operandenstapel. Der tatsächliche Typ des Objekts, auf das das erste Element oben zeigt, bezeichnet als

C

  • 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 genannt
  • Implementierung der dynamischen Zuweisung virtueller MaschinenDie Methoden zur Analyse des Konzepts virtueller Maschinen sind statische Zuweisung und dynamische Zuweisung. Sie können die Frage verstehen: „Was wird eine virtuelle Maschine während der Zuweisung tun?“

    Wie 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

    • Methoden mit derselben Signatur in der übergeordneten Klasse und der Unterklasse Die virtuelle Methodentabelle hat dieselbe Indexnummer:

    • Auf diese Weise müssen Sie bei einer Typänderung nur die nachzuschlagende Methodentabelle ändern. und die erforderliche Eintragsadresse kann entsprechend dem Index aus verschiedenen virtuellen Methodentabellen konvertiert werden
    • 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!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen