To, co static
oznacza modyfikator, gdy jest stosowany do deklaracji zmiennej, to fakt, że zmienna jest zmienną klasy, a nie zmienną instancji. Innymi słowy ... jest tylko jedna num1
zmienna i tylko jedna num2
zmienna.
(Poza tym: zmienna statyczna jest podobna do zmienna globalna w niektórych innych językach, z tą różnicą, że jej nazwa nie jest widoczna wszędzie. Nawet jeśli jest zadeklarowana jako a public static
, niekwalifikowana nazwa jest widoczna tylko wtedy, gdy jest zadeklarowana w bieżącej klasie lub nadklasie lub jeśli jest importowany przy użyciu importu statycznego. Na tym polega różnica. Prawdziwy globalny jest wszędzie widoczny bez kwalifikacji).
Więc kiedy odnoszą się do obj.num1
i obj.num2
, w rzeczywistości odnosi się do tych zmiennych statycznych, których nazwy są prawdziwe A.num1
i A.num2
. I podobnie, gdy konstruktor zwiększa wartość num1
inum2
, zwiększa te same zmienne (odpowiednio).
Myląca kwestia w twoim przykładzie dotyczy inicjalizacji klasy. Klasa jest inicjowana przez pierwszą domyślną inicjalizację wszystkich zmiennych statycznych, a następnie wykonywanie zadeklarowanych inicjatorów statycznych (i bloków inicjatorów statycznych) w kolejności, w jakiej pojawiają się w klasie. W tym przypadku masz to:
static A obj = new A();
static int num1;
static int num2=0;
Dzieje się tak:
Statyka zaczyna się od domyślnych wartości początkowych; A.obj
jest null
i A.num1
/ A.num2
są zerem.
Pierwsza deklaracja ( A.obj
) tworzy wystąpienie A()
i konstruktor dla A
inkrementacji A.num1
i A.num2
. Gdy deklaracja zakończy się, A.num1
i A.num2
są oba 1
, i A.obj
odwołuje się do nowo utworzonego A
wystąpienia.
Druga deklaracja ( A.num1
) nie ma inicjatora, więc A.num1
się nie zmienia.
Trzecia deklaracja ( A.num2
) ma inicjator, który przypisuje zero do A.num2
.
Tak więc pod koniec inicjalizacji klasy A.num1
jest 1
i A.num2
jest0
... i to właśnie pokazują twoje instrukcje print.
To mylące zachowanie jest tak naprawdę spowodowane faktem, że tworzysz instancję przed zakończeniem inicjalizacji statycznej i że konstruktor, którego używasz, zależy od statycznej, która nie została jeszcze zainicjowana, i modyfikuje ją. To coś, czego powinieneś unikać w prawdziwym kodzie.