Heim  >  Artikel  >  Java  >  Ausführliche Erläuterung des Java-Schlüsselworts this (Anordnung des Leistungsknotens)

Ausführliche Erläuterung des Java-Schlüsselworts this (Anordnung des Leistungsknotens)

黄舟
黄舟Original
2017-03-31 10:28:271443Durchsuche

Dies ist in Java überall zu sehen und hat viele Verwendungsmöglichkeiten. Unter normalen Umständen ist es sehr einfach, dieses Schlüsselwort zu verstehen. Als ich jedoch mit dem Lernen begann, hatte ich eine Frage, die ich nicht klar verstehen konnte. Jetzt werde ich sie für alle als Referenz aufzeichnen Freunde in Not. Weiter

Wenn wir in Java normalerweise das Schlüsselwort this verwenden, wissen wir alle, dass dies die aktuelle Instanz der Methode darstellt, die diese Klasse aufruft. Unter normalen Umständen ist es einfach, dieses Schlüsselwort zu verstehen, aber als ich anfing zu lernen, hatte ich eine Frage, die ich nicht klar verstehen konnte. Jetzt, da ich sie langsam verstehe, möchte ich sie aufschreiben Problem wie ich. Vielleicht kann es anderen helfen. Schauen wir uns zunächst kurz an, welche Rolle dies unter normalen Umständen spielt. Zum Beispiel der folgende Code:

public class Leaf {
 private int i = 0;
 Leaf increment() {
  i++;
  return this;
 }
 void print() {
  System.out.println("i = " + i);
 }
 public static void main(String[] args) {
  Leaf x = new Leaf();
  x.increment().increment().print();
 }
}

In der Hauptmethode der Leaf-Klasse erstellen wir eine neue Leaf-Instanz x, und dann ruft die x-Instanz die Methode increment() auf. Wenn increment() eine normale Methode oder eine Void-Methode ist, gibt es an dieser Stelle nichts, was es wert wäre, studiert zu werden. Das Besondere ist, dass wir in der increment()-Methode Folgendes zurückgeben, und dieses Dies stellt das x dar, das wir gerade erstellt haben. Da x die Methode increment() aufruft, stellt die Methode increment() offensichtlich die x-Instanz von Leaf dar.

Dies scheint nichts zu besprechen, dies stellt die Instanz x dar, die diese Methode aufruft. Wenn wir jedoch die main()Funktion so ändern, dass sie wie folgt aussieht

public static void main(String[] args) {
 Leaf x = new Leaf();
 x.increment().increment().print();
  
 Leaf y = new Leaf();
 y.increment().increment().print();
}

Im oben geänderten Code erstellen wir eine neue Leaf-Instanz y, und dann wird auch y aufgerufen kontinuierlich zweimal inkrementieren. Die Frage ist nun: Wenn x und y gleichzeitig die Methode increment() aufrufen, wen kann dies dann darstellen? Sie denken vielleicht, dass daran etwas nicht stimmt. Wenn x die Methode increment() aufruft, repräsentiert dies x. Das Problem besteht jedoch darin, dass wir auf der JVM-Ebene die Speicheradresse finden, an der sich die increment()-Methode in der Leaf-Klasse befindet, und dann einen Stapelrahmen im Java Virtual Machine-Stapel
erstellen

Führen Sie dann den Code innerhalb der Methode im Stapelrahmen aus. Nun sehen Sie, dass es auf der Ebene der JVM-Ausführungsmethode keinen sogenannten x-Aufruf gibt, sondern y. Wie bestimmt dies dann in der Methode, auf welche Instanz sie zeigt?

Schauen wir uns an, wie es im Bytecode der Leaf-Klasse angezeigt wird. Wenn wir die x-Instanz oder die y-Instanz nicht an die Methode übergeben, führen wir die Methode in der JVM aus Es ist unmöglich zu wissen, auf welche Instanz dies konkret hinweist.

An diesem Punkt sehen wir, dass es in der increment()-Methode keine Parameter in der Codierung gibt, aber die Anzahl der Parameter im Bytecode wird mit 1 angezeigt. Wenn wir darüber nachdenken Bei sorgfältiger Betrachtung ist das Ergebnis bereits offensichtlich: Wenn die JVM eine Kompilierung durchführt, wird in der Instanzmethode standardmäßig ein Parameter ausgeblendet. Wenn beispielsweise x aufgerufen wird, wird x übergeben, wenn es ausgeblendet ist, und wenn y aufgerufen wird, wird y übergeben. Daher kann unser this auf der Ebene der JVM-Ausführungsmethode bestimmen, auf wen er verweist.

Die obige Schlussfolgerung ist unsere eigene Schlussfolgerung. Gibt es ein Buch, das dies im Detail beschreibt? In „JavaProgrammierungGedanken“ wird dieser Abschnitt wie folgt beschrieben:

Angenommen, wir befinden uns in einer Methode und möchten das Handle des aktuellen -Objekts erhalten. Da dieses Handle „heimlich“ vom Compiler übergeben wird, ist kein Bezeichner verfügbar. Dafür gibt es jedoch ein eigenes Schlüsselwort: this.

Das vom darin erwähnten Compiler heimlich übergebene Handle ist der versteckte Parameter, den wir hier haben.

Bisher muss die Beschreibung hierfür sehr klar sein, und wir verstehen sie auf JVM-Ebene. Sind Sie daran interessiert, einen Blick auf das folgende Beispiel zu werfen und darüber nachzudenken, was dies in der Basisklasse B darstellt?

public class B {
 public B() {
  System.out.println(this.getClass().getSimpleName()); 
  System.out.println(((A) this).a); 
 }
}
public class A extends B {
 public int a = 100;  
 public A() {
  a = 200;
 } 
 public static void main(String[] args) {
  new A();
 }
}

Dieses Beispiel sollte ursprünglich verstehen, wie eine Klasse initialisiert wird, wenn Java eine Vererbungsstruktur hat, aber der Konstruktor in Klasse B hier ist etwas ganz Besonderes: Der dadurch im Konstruktor in Klasse B ausgegebene SimpleName ist A. Wenn wir auf diese Situation stoßen, sollte der von dieser Klasse B ausgegebene SimpleName normalerweise B sein, aber hier ist er A? Warum?

Während wir oben darüber gesprochen haben, haben wir dies bereits angesprochen. Beim Aufrufen der Java-Methode zum Erstellen eines Stapelrahmens übergibt der JVM heimlich eine aktuelle Instanz. Wenn wir den Konstruktor von A ausführen, wird daher standardmäßig der Konstruktor der übergeordneten Klasse B aufgerufen. Wenn der Konstruktor der übergeordneten Klasse B aufgerufen wird, ist die aktuell übergebene Instanz die Instanz von A, da B aufgerufen wird der Konstruktor von A, daher repräsentiert dies hier stattdessen A.

Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung des Java-Schlüsselworts this (Anordnung des Leistungsknotens). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn