Frage

public class Main {

    static int x = Main.y;
//  static int x = y; //Not allowed; y is not defined
    static int y = x;
    public static void main(String[] args) {
        System.out.println(x);//prints 0
    }
}

Wie komme ich zum Einsatz y Trog der Klasse erlaubt bin, aber nicht direkt?

Wenn y definiert?

War es hilfreich?

Lösung

Die genauen Regeln Vorwärtsverweis auf Klassenvariablen regeln, werden im Abschnitt §8.3.2.3 der JLS:

8.3.2.3 Einschränkungen bei der Verwendung von Feldern bei der Initialisierung

Die Erklärung eines Mitglieds muss textlich erscheinen, bevor sie verwendet wird, nur dann, wenn das Element ist eine Instanz (Bzw. static) Feld einer Klasse oder C-Schnittstelle und alle die folgende Bedingungen erfüllt sind:

  • Die Verwendung erfolgt in einer Instanz (bzw. static) Variable Initialisierer von C oder in einer Instanz (Bzw. static) Initialisierer von C.
  • Die Verwendung ist nicht auf der linken Seite einer Zuweisung.
  • Die Verwendung erfolgt über einen einfachen Namen.
  • C ist die innerste Klasse oder Schnittstelle die Verwendung umschließt.

Ein Fehler bei der Kompilierung tritt auf, wenn die die vier Anforderungen sind oben nicht Met.

Das bedeutet, dass ein Fehler bei der Kompilierung Ergebnisse aus dem Testprogramm:

  class Test {
      int i = j;  // compile-time error: incorrect forward reference
      int j = 1;
  }

, während die folgende Beispiel compiliert ohne Fehler:

  class Test {
      Test() { k = 2; }
      int j = 1;
      int i = j;
      int k;
  }

Auch wenn der Konstruktor (§8.8) für Test bezieht sich auf die Feld k, der drei Zeilen deklariert später.

Diese Einschränkungen ausgelegt Fangen, zum Zeitpunkt der Kompilierung, kreisförmig oder sonst Initialisierungen malformed. Somit können sowohl:

class Z {
  static int i = j + 2; 
  static int j = 4;
}

und

class Z {
  static { i = j + 2; }
  static int i, j;
  static { j = 4; }
}

Ergebnis in Kompilierung-Fehler. Zugriffe durch Methoden sind nicht eingecheckt Auf diese Weise, so:

class Z {
  static int peek() { return j; }
  static int i = peek();
  static int j = 1;
}
class Test {
  public static void main(String[] args) {
      System.out.println(Z.i);
  }
}

erzeugt die Ausgabe:

0

, weil die Variableninitialisierer für i verwendet die Klassenmethode peek auf Zugang der Wert der Variablen j vor j wurde durch seine Variable initialisiert initializer, an welcher Stelle es noch hat seinen Standardwert (§4.12.5) .

Andere Tipps

Ich würde davon ausgehen, dass durch die Klasse verwendet wird, würde aufschieben der Compiler für die Variable suchen, bis die Klasse abgeschlossen war, so ist es y findet, aber wenn Sie es gerade wie der Kommentar definieren es ist noch nicht definiert, so scheitert es

Statische Variablen werden in der Reihenfolge der Deklaration in der Klasse definiert, während das Laden von Klassen. Wenn die JVM die Main Klasse laden, wird x definiert werden, dann y. Deshalb sollten Sie nicht direkt y verwenden können, wenn x Initialisierung erstellen Sie etwas, das eine heißt Vorwärts-Referenz , verweist auf eine Variable ist nicht definiert, und das ist illegal für den Compiler.

Wenn Main.y will, gibt man folgendes passiert:

  • Sie Last Main, x Initialisierung genannt
  • Wenn Sie x definieren Gleichen Main.y zu sein, sieht der Compiler einen Verweis auf eine Klasse, so wird es x auf den aktuellen Wert des Elements y der Klasse Main Ende definiert. Es behandelt diesen Fall als ob Main eine andere Klasse.

Beachten Sie, dass in diesem Fall, wenn x initialisiert hat y nicht für den Moment definiert werden. So x einen Wert von 0 haben.

Sie sind nicht erlaubt, es zu tun, weil es sinnlos ist. Die einzig mögliche Interpretation ist, dass y auf Null initialisiert, und Sie haben bereits zwei Möglichkeiten, das zu sagen. Sie haben nicht diese benötigen.

Vielleicht ist der Compiler erstellt die Referenzen der statischen Variablen mit Standardwerten mit der Klasse in dem Stapel, wenn es erstellt wird und dann ordnet die angegebenen Werte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top