Heim  >  Artikel  >  Java  >  Erläuterung des Aufrufs des Java-Basisklassenkonstruktors (mit Code)

Erläuterung des Aufrufs des Java-Basisklassenkonstruktors (mit Code)

不言
不言nach vorne
2018-10-08 15:03:412444Durchsuche

Der Inhalt dieses Artikels ist eine Erklärung des Aufrufs des Java-Basisklassenkonstruktors (mit Code). Ich hoffe, dass er für Freunde hilfreich ist.

Es gibt eine solche Passage in Kapitel 7 der Wiederverwendungsklassen in „Gedanken zur Java-Programmierung“, über die es sich lohnt, nachzudenken. Wenn eine Unterklasse eine übergeordnete Klasse erbt, umfasst sie zwei Klassen: die Basisklasse und die abgeleitete Klasse (Unterklasse). Von außen sieht eine abgeleitete Klasse wie eine neue Klasse mit derselben Schnittstelle wie die Basisklasse aus, möglicherweise mit einigen zusätzlichen Methoden und Feldern. Bei der Vererbung wird jedoch nicht nur die Schnittstelle der Basisklasse kopiert. Wenn Sie ein exportiertes Klassenobjekt erstellen, enthält das Objekt ein Unterobjekt der Basisklasse. Dieses Unterobjekt ist dasselbe wie das Objekt, das Sie direkt mit der Basisklasse erstellen außerhalb, während die Unterobjekte der Basisklasse in abgeleitete Klassenobjekte eingeschlossen sind.

Dies wirft ein sehr wichtiges Problem auf. Die korrekte Initialisierung des Unterobjekts der Basisklasse ist ebenfalls von entscheidender Bedeutung (wir können die von der Basisklasse geerbten Methoden und Felder in der Unterklasse verwenden), und das ist auch der Fall Es gibt nur eine Möglichkeit, dies sicherzustellen: Rufen Sie den Basisklassenkonstruktor im Unterklassenkonstruktor auf, um die Initialisierung durchzuführen.

Parameterloser Basisklassenkonstruktor

Wir wissen, dass Java automatisch den parameterlosen Konstruktor für Sie aufruft, wenn Sie ihm keinen Konstruktor für eine Klasse geben, und Java wird ihn auch exportieren zum Basisklassenkonstruktor in den Klassenkonstruktor. Der folgende Code veranschaulicht diesen Arbeitsmechanismus:

//: reusing/Cartoon.java
// Constructor calls during inheritance.
import static net.mindview.util.Print.*;

class Art {
  Art() { print("Art constructor"); }
}

class Drawing extends Art {
  Drawing() { print("Drawing constructor"); }
}

public class Cartoon extends Drawing {
  public Cartoon() { print("Cartoon constructor"); }
  public static void main(String[] args) {
    Cartoon x = new Cartoon();
  }
} /* Output:
Art constructor
Drawing constructor
Cartoon constructor
*///:~

Beobachten Sie die laufenden Ergebnisse des obigen Codes. Beim Erstellen eines Cartoon-Objekts wird zuerst der Konstruktor seiner übergeordneten Klasse Drawing aufgerufen und seine übergeordnete Klasse erbt von Art Der Konstruktor der Art-Klasse wird also erneut aufgerufen, genau wie Schicht für Schicht. Obwohl der Konstruktor der übergeordneten Klasse in seinem Konstruktor nicht explizit aufgerufen wird, ruft Java automatisch den Konstruktor seiner übergeordneten Klasse auf. Selbst wenn Sie keinen Konstruktor für Cartoon() erstellen, synthetisiert der Compiler einen Standardkonstruktor ohne Argumente, der den Konstruktor der Basisklasse aufruft.

Basisklassenkonstruktor mit Parametern

Wenn der Konstruktor in der Basisklasse Parameter hat, ruft der Compiler ihn nicht automatisch auf und muss explizit mit dem Schlüsselwort super aufgerufen und übergeben werden Die entsprechenden Parameter lauten wie folgt:

//: reusing/Chess.java
// Inheritance, constructors and arguments.
import static net.mindview.util.Print.*;

class Game {
  Game(int i) {
    print("Game constructor");
  }
}

class BoardGame extends Game {
  BoardGame(int i) {
    super(i);
    print("BoardGame constructor");
  }
}   

public class Chess extends BoardGame {
  Chess() {
    super(11);
    print("Chess constructor");
  }
  public static void main(String[] args) {
    Chess x = new Chess();
  }
} /* Output:
Game constructor
BoardGame constructor
Chess constructor
*///:~

Wie aus dem obigen Code hervorgeht, muss der Superklassenkonstruktor explizit im Unterklassenkonstruktor aufgerufen werden und die entsprechenden Parameter übergeben. Darüber hinaus muss der Aufruf des Basisklassenkonstruktors als Erstes im Unterklassenkonstruktor erfolgen.

Das Problem der Aufrufsequenz des Basisklassenkonstruktors

Davor besprechen wir zunächst das Initialisierungsproblem der Objektreferenz. In Java können Felder in einer Klasse automatisch auf Null initialisiert werden, wenn es sich um Basistypen handelt, Objektverweise werden jedoch auf Null initialisiert. Wir müssen es oft an der entsprechenden Stelle initialisieren. Hier sind mehrere Orte, an denen die Initialisierung durchgeführt werden kann:

Wo das Objekt definiert ist. Das bedeutet, dass sie immer initialisiert werden können bevor der Konstruktor aufgerufen wird.

2. Im Konstruktor der Klasse.

3. Unmittelbar vor der Verwendung dieser Objekte wird diese Methode als verzögerte Initialisierung bezeichnet.

Erinnern wir uns an Punkt 1 oben und schauen wir uns ein komplexeres Beispiel an, um die Aufrufreihenfolge des Basisklassenkonstruktors zu betrachten.

// reusing/Ex7/C7.java
// TIJ4 Chapter Reusing, Exercise 7, page 246
/* Modify Exercise 5 so that A and B have constructors with arguments instead
* of default constructors. Write a constructor for C and perform all 
* initialization within C's constructor. 
*/
 
import static org.greggordon.tools.Print.*;

class A { 
    A(char c, int i) { println("A(char, int)");} 
}

class B extends A {     
    B(String s, float f){
        super(' ', 0); 
        println("B(String, float)");
    } 
}

class C7 extends A { 
    private char c;
    private int i;
    C7(char a, int j) {     
        super(a, j); 
        c = a;
        i = j;
    }
    B b = new B("hi", 1f); // will then construct another A and then a B
    public static void main(String[] args) {
        C7 c = new C7('b', 2); // will construct an A first
    }
}

Die obige Codeausgabe:

A(char, int)

A(char, int)

B(String, float)

Achten Sie auf die Reihenfolge der Initialisierung des Basisklassenkonstruktors, des Unterklassenkonstruktors und des Klassenmitgliedsobjekts:

1. Wenn ein Objekt einer Klasse neu ist, rufen Sie zuerst den Konstruktor der übergeordneten Klasse auf (kann ohne Parameter oder mit Parametern versehen sein, das System ruft automatisch den Konstruktor ohne Parameter auf und Sie müssen ihn selbst angeben, wenn Parameter vorhanden sind). Zum Beispiel super(a, j)

2 in C7 oben. Führen Sie dann die Initialisierungsanweisung für das Mitgliedsobjekt aus und rufen Sie den Konstruktor der Klasse B auf, wie oben
B b = new B("hi", 1f), und der Konstruktor von B ruft zuerst den Konstruktor der Basisklasse A auf.

3. Kehren Sie abschließend zum Konstruktor in C7 zurück und fahren Sie mit der Ausführung von c=a,i=j fort.

Das obige ist der detaillierte Inhalt vonErläuterung des Aufrufs des Java-Basisklassenkonstruktors (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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