web-dev-qa-db-de.com

Kann nicht auf "X" verweisen, bevor der Supertypkonstruktor aufgerufen wurde, wobei x eine letzte Variable ist

Beachten Sie die folgende Java-Klassendeklaration:

public class Test {

    private final int defaultValue = 10;
    private int var;

    public Test() {
        this(defaultValue);    // <-- Compiler error: cannot reference defaultValue before supertype constructor has been called.
    }

    public Test(int i) {
        var = i;
    }
}

Der Code wird nicht kompiliert. Der Compiler beschwert sich über die Zeile, die ich oben hervorgehoben habe. Warum geschieht dieser Fehler und was ist die beste Problemumgehung?

60
Amr Bekhit

Der Grund für die anfängliche Kompilierung des Codes ist, dass defaultValue eine instanzvariable der Klasse Test ist. Dies bedeutet, dass bei der Erstellung eines Objekts vom Typ Test eine eindeutige Instanz von defaultValue erstellt und an dieses Objekt angehängt wird . Aus diesem Grund ist es nicht möglich, auf defaultValue im Konstruktor zu verweisen, da weder er noch das Objekt erstellt wurden.

Die Lösung besteht darin, die letzte Variable static zu machen:

public class Test {

    private static final int defaultValue = 10;
    private int var;

    public Test() {
        this(defaultValue);
    }

    public Test(int i) {
        var = i;
    }
}

Indem Sie die Variable static festlegen, wird sie mit der Klasse selbst und nicht mit Instanzen dieser Klasse verknüpft. Sie wird von allen Instanzen von Test gemeinsam genutzt. Statische Variablen werden erstellt, wenn die JVM die Klasse zum ersten Mal lädt. Da die Klasse bereits beim Erstellen einer Instanz geladen wird, ist die statische Variable einsatzbereit und kann in der Klasse einschließlich des Konstruktors verwendet werden.

Verweise:

84
Amr Bekhit

Dies liegt daran, dass die Variable defaultValue ein Mitglied der Instanz von Test ist, die sich im Aufbau befindet (noch nicht erstellt). 

Wenn Sie static hatten, wurde es geladen, wenn Ihre Klasse von Classloadern geladen wurde

8
Jigar Joshi

Regel: Jeder Konstruktor muss den Konstruktor der Superklasse ausführen, bevor er sich selbst ausführt.

Die erste Zeile jedes Konstruktors ist also super () oder kann this () sein, und Sie senden den defaultValue an diesen Klassenkonstruktor, der (defaultValue) noch nicht vorhanden ist. Daher liegt ein Fehler beim Kompilieren vor.

Sie können defaultValue als statisch festlegen, da die statische Variable erstellt wird, während die Klasse in den Arbeitsspeicher geladen wird. StandardValue ist also in der Zeile this (defaultValue) verfügbar.

4
Himanshu Mohta

sie referenzieren auf eine Variable, die dosen't noch nicht existiert, Wenn es static war, wird es sogar vor dem Konstruktor selbst vorhanden sein. 

sie werden jedoch mit einem anderen Problem konfrontiert, da defaultValue statisch geworden ist. Daher haben alle anderen Instanzen möglicherweise denselben Wert, den Sie möglicherweise nicht mögen.

public class Test {

    private final int defaultValue = 10; //this will be exists only after calling the contractor
    private final static int vakue2= 10; //this is exists before the contractor has been called
    private int var;

    public Test() {
       // this(defaultValue);    // this metod will not work as defaultValue doesn't exists yet
    this(value2); //this will work
    //this(10); will work
    }

    public Test(int i) {
        var = i;
    }
}
2
Sherif Eldeeb

Erst wenn Ihr Objekt nicht erstellt wurde, werden keine Standardwerte für die Variablen festgelegt. Wenn Sie die Standardwerte zum Zeitpunkt der Erstellung festlegen möchten, müssen Sie sie als static festlegen oder sie explizit vorher festlegen.

1
amicngh

der Konstruktor wird zum Zeitpunkt der Objekterstellung aufgerufen. Daher wird vom Compiler im Compiler kein Verweis auf eine Variable erkannt. Die Instanzvariablen sind nicht bekannt, da das Objekt noch nicht erstellt wurde.

0
Hardik Mehta

Tatsächlich ist dies keine richtige Antwort, da während der Erstellung von Objekt-Initialisierungsanweisungen Felder vor dem Konstruktor ausgeführt werden. Sie können den Objekterstellungsprozess debuggen und das selbst anzeigen. Ich selbst bin auch verwirrt über dieses Problem. Zum Beispiel, wenn Sie ein wenig ändern und der erste Konstruktor sein wird:

public Test(int i) {
   this(i, 0);
}
public Test (int a, int k) {
}

Das wird funktionieren. Wenn also der erste/null-Konstruktor einen anderen aufruft, funktioniert das aus einem seltsamen Grund nicht, auch wenn ich super () explizit aufrufe. Vor.

Die relevanteste Erklärung wäre, dass die JVM Deklarationen in den Speicher lädt, aber NO CONSTRUCTOR IS MÖGLICH, EINEN INSTANZ VARIABLE/FIELD zu erreichen, bevor sie vollständig ausgeführt wird.

0