Home  >  Article  >  Java  >  Complete analysis of initialization of static variables in Java

Complete analysis of initialization of static variables in Java

高洛峰
高洛峰Original
2017-01-24 17:03:202217browse

Static variable initialization sequence
1. Simple rules

First look at the most common JAVA code:

public class Test
{
 public static Test1 t = new Test1();
 public static int a = 0;
 public static int b;
 
 public static void main(String[] arg)
 {
  System.out.println(Test.a);
  System.out.println(Test.b);
 }
}
 
class Test1
{
 public Test1()
 {
  Test.a++;
  Test.b++;
 }
}

Let’s guess what the console output is?

OK, maybe you have guessed the result below, then you are still familiar with Java.

0 1

If you don’t understand why the above result is output, then let me tell you.


Java static variable initialization follows the following rules:

Static variables will be declared in the order of declaration and set to the default value of the type, but not Assign the initialized value.

After the declaration is completed, set the initialized values ​​in the order of declaration. If there is no initialized value, skip it.

After reading this, you will understand that the value of Test.a has changed three times.

Set to 0 when declaring>>Test1::Set to 1 in Test1>>Test.a is initialized to 0

2. Complex rules

I understand this , please look at the code below again.

public class A
{
 public static int b = B.a;
 public static A plus =new A("A");
 public static final int finalInt = (int)(Math.random()*100);
 public static B p = new B("A");
 
 public static final String finalStr = "finalStr";
 public static final Integer finalInteger = new Integer(10);
 public static int a = 1;
 public static B c = null;
 
 public A(String from)
 {
  System.out.println("----------- begin A::A ----------------");
  System.out.println("A::A, from="+from);
  System.out.println("A::A, A.b="+A.b);
  System.out.println("A::A, A.finalInt="+A.finalInt);
  System.out.println("A::A, B.a="+B.a);
  System.out.println("A::A, B.plus="+B.plus);
  System.out.println("----------- end A::A ----------------");
 }
 
 public static void main(String[] arg)
 {
  System.out.println("main, A.b="+A.b);
  System.out.println("main, B.t="+B.t);
  System.out.println("main, C.a="+C.a);
 }
}
 
class B
{
 public static int t = A.a;
 public static A plus = new A("B");
 public static int a = 1;
 
 public B(String from)
 {
  System.out.println("----------- begin B::B ----------------");
  System.out.println("B::B, from="+from);
  System.out.println("B::B, B.a="+B.a);
  System.out.println("B::B, A.a="+A.a);
  System.out.println("B::B, A.p="+A.p);
  System.out.println("B::B, A.plus="+A.plus);
  System.out.println("B::B, A.finalInt="+A.finalInt);
  System.out.println("B::B, A.finalInteger="+A.finalInteger);
  System.out.println("B::B, A.finalStr="+A.finalStr);
  System.out.println("----------- end B::B ----------------");
 }
}
 
class C
{
 public static final A a = new A("C");
}

Can you still guess the output result? I was writing it while testing, so I didn’t guess it. Haha

The console output result is:

----------- begin A::A ----------------
A::A, from=B
A::A, A.b=0
A::A, A.finalInt=0
A::A, B.a=0
A::A, B.plus=null
----------- end A::A ----------------
----------- begin A::A ----------------
A::A, from=A
A::A, A.b=1
A::A, A.finalInt=0
A::A, B.a=1
A::A, B.plus=A@a90653
----------- end A::A ----------------
----------- begin B::B ----------------
B::B, from=A
B::B, B.a=1
B::B, A.a=0
B::B, A.p=null
B::B, A.plus=A@1fb8ee3
B::B, A.finalInt=61
B::B, A.finalInteger=null
B::B, A.finalStr=finalStr
----------- end B::B ----------------
main, A.b=1
main, B.t=0
----------- begin A::A ----------------
A::A, from=C
A::A, A.b=1
A::A, A.finalInt=61
A::A, B.a=1
A::A, B.plus=A@a90653
----------- end A::A ----------------
main, C.a=A@61de33

You didn't guess this result, haha.

To explain the program execution result sentence by sentence, it still takes a lot of space. Here I will directly write down the rules followed by Java static variable initialization.

The rules in the first paragraph are still valid, but they are not sound.

Only when a class is actively requested, this class will be initialized, and it only contains static variables, functions, and other static things.

When inheriting a relationship, the parent class is initialized first, and then the subclass is initialized.

Static variables will be declared in the order of declaration and set to the default value of the type, but will not be assigned the initialized value.

After the declaration is completed, they will be set in the order of declaration. is the initialized value, if there is no initialized value, skip.

When initializing A.b=B.a, pause the initialization of A.b, set the current class to B, jump to step 3, and execute.

When initializing B.plus = new A, pause the initialization of B.plus, instantiate A and assign it to B.plus.

When the value of B.a needs to be obtained in the constructor of A, B.a is also initialized and In the paused initialization state, directly take the current value of B.a without waiting for B.a to be initialized.

final, static constants actually follow the initialization of ordinary static variables, but at compile time, the compiler will change the immutable Constant values ​​are replaced where used. You can use Java decompilation tools to view.

Initialization of static data
Added static qualified fields are so-called class fields, which means that the ownership of this field It is not an object but a class. No matter how many objects are created, there is only one copy of static data.

Always initialize static fields first and then initialize general fields within a class. Then initialize the constructor. But if an object of this class is not created, the object will not be initialized and will only be executed once.

As shown in the following code, in the StaticInitialization class, first initialize static Table table = new Table();, and then initialize the Table object, otherwise it will not be initialized.

class Bowl {
 Bowl(int marker) {
 print("Bowl(" + marker + ")");
 }
 void f1(int marker) {
 print("f1(" + marker + ")");
 }
}
 
class Table {
 static Bowl bowl1 = new Bowl(1);
 Table() {
 print("Table()");
 bowl2.f1(1);
 }
 void f2(int marker) {
 print("f2(" + marker + ")");
 }
 static Bowl bowl2 = new Bowl(2);
}
 
class Cupboard {
 Bowl bowl3 = new Bowl(3);
 static Bowl bowl4 = new Bowl(4);
 Cupboard() {
 print("Cupboard()");
 bowl4.f1(2);
 }
 void f3(int marker) {
 print("f3(" + marker + ")");
 }
 static Bowl bowl5 = new Bowl(5);
}
 
public class StaticInitialization {
 public static void main(String[] args) {
 print("Creating new Cupboard() in main");
 new Cupboard();
 print("Creating new Cupboard() in main");
 new Cupboard();
 table.f2(1);
 cupboard.f3(1);
 }
 static Table table = new Table();
 static Cupboard cupboard = new Cupboard();
}

Output:

Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)

Displayed static initialization (that is, static block)
Wrapping multiple initialization statements in a static curly brace is called a static block. In fact, it is multiple initialization statements. The two statics are written together, and the essence is the same. It will only be executed when the object is first created or when a field of the class is accessed for the first time, and only once.

class Cup {
 Cup(int marker) {
 print("Cup(" + marker + ")");
 }
 void f(int marker) {
 print("f(" + marker + ")");
 }
}
 
class Cups {
 static Cup cup1;
 static Cup cup2;
 static {
 cup1 = new Cup(1);
 cup2 = new Cup(2);
 }
 Cups() {
 print("Cups()");
 }
}
 
public class ExplicitStatic {
 public static void main(String[] args) {
 print("Inside main()");
 Cups.cup1.f(99); // (1)
 }
 // static Cups cups1 = new Cups(); // (2)
 // static Cups cups2 = new Cups(); // (2)
}

Output:

Inside main()
Cup(1)
Cup(2)
f(99)


Non-static instance initialization
There is nothing to say about this, it is ordinary initialization, executed in order, and can be executed multiple times .

class Mug {
 Mug(int marker) {
 print("Mug(" + marker + ")");
 }
 void f(int marker) {
 print("f(" + marker + ")");
 }
}
 
public class Mugs {
 Mug mug1;
 Mug mug2;
 {
 mug1 = new Mug(1);
 mug2 = new Mug(2);
 print("mug1 & mug2 initialized");
 }
 Mugs() {
 print("Mugs()");
 }
 Mugs(int i) {
 print("Mugs(int)");
 }
 public static void main(String[] args) {
 print("Inside main()");
 new Mugs();
 print("new Mugs() completed");
 new Mugs(1);
 print("new Mugs(1) completed");
 }
}
Inside main()
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(int)
new Mugs(1) completed

For more articles related to the complete analysis of the initialization of static static variables in Java, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn