static
Wenn der Modifikator auf eine Variablendeklaration angewendet wird, bedeutet dies, dass die Variable eher eine Klassenvariable als eine Instanzvariable ist. Mit anderen Worten ... es gibt nur eine num1
Variable und nur eine num2
Variable.
(Abgesehen: eine statische Variable ist wie . Eine globale Variable in einigen anderen Sprachen, mit der Ausnahme , dass sein Name nicht überall sichtbar ist , auch wenn es als deklariert wird public static
, ist der unqualifizierte Name nur dann sichtbar , wenn es in der aktuellen Klasse oder eine übergeordneten Klasse deklariert wird oder wenn es mit einem statischen Import importiert wird. Das ist der Unterschied. Ein echtes globales ist ohne Qualifikation irgendwo sichtbar.)
Wenn Sie sich also auf obj.num1
und beziehen, beziehen obj.num2
Sie sich tatsächlich auf die statischen Variablen, deren tatsächliche Bezeichnungen A.num1
und sind A.num2
. Und in ähnlicher Weise erhöht der Konstruktor, wenn er inkrementiert num1
und num2
, dieselben Variablen (jeweils).
Die verwirrende Falte in Ihrem Beispiel liegt in der Klasseninitialisierung. Eine Klasse wird standardmäßig initialisiert, indem zunächst alle statischen Variablen initialisiert und dann die deklarierten statischen Initialisierer (und statischen Initialisiererblöcke) in der Reihenfolge ausgeführt werden, in der sie in der Klasse angezeigt werden . In diesem Fall haben Sie Folgendes:
static A obj = new A();
static int num1;
static int num2=0;
Es passiert so:
Die Statik beginnt mit ihren Standardanfangswerten. A.obj
ist null
und A.num1
/ oder A.num2
sind Null.
Die erste Deklaration ( A.obj
) erstellt eine Instanz von A()
und den Konstruktor für A
Inkremente A.num1
und A.num2
. Wenn die Deklaration abgeschlossen ist A.num1
und A.num2
beides 1
ist und A.obj
sich auf die neu erstellte A
Instanz bezieht .
Die zweite Deklaration ( A.num1
) hat keinen Initialisierer und A.num1
ändert sich daher nicht.
Die dritte Deklaration ( A.num2
) hat einen Initialisierer, dem Null zugewiesen wird A.num2
.
Am Ende der Klasseninitialisierung A.num1
ist 1
und A.num2
ist also 0
... und das zeigen Ihre Druckanweisungen.
Dieses verwirrende Verhalten ist darauf zurückzuführen, dass Sie eine Instanz erstellen, bevor die statische Initialisierung abgeschlossen ist, und dass der von Ihnen verwendete Konstruktor von einer noch zu initialisierenden Statik abhängt und diese ändert . Dies sollten Sie in echtem Code vermeiden.