当前位置: 移动技术网 > IT编程>开发语言>Java > Java中static静态变量的初始化完全解析

Java中static静态变量的初始化完全解析

2019年07月22日  | 移动技术网IT编程  | 我要评论
静态变量初始化顺序 1.简单规则 首先先看一段最普遍的java代码: public class test { public static test1 t

静态变量初始化顺序
1.简单规则

首先先看一段最普遍的java代码:

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++;
 }
}

这里先猜下控制台输出结果是什么?

ok, 或许你已经猜到下面了结果了,那么你还是熟悉java的。

复制代码 代码如下:
0 1

如果你不明白是为什么会输出上面的结果,那么我来告诉你。

java静态变量初始化遵循以下规则:

  • 静态变量会按照声明的顺序先依次声明并设置为该类型的默认值,但不赋值为初始化的值。
  • 声明完毕后,再按声明的顺序依次设置为初始化的值,如果没有初始化的值就跳过。

看了这个就会明白,原来test.a的值变化了三次。

声明时设置为0>>test1::test1里设置为1>>test.a初始化为0

2.复杂规则

明白了这个,请再看下面的代码。

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");
}

这个你还能猜到输出结果吗? 我是在一边测试一边写的,所以我没猜出来.哈哈

控制台输出结果为:

----------- 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

这个结果你没猜到吧,哈哈.

要一句一句的讲解程序执行结果,还是要很到的篇幅的.这里就直接写出java静态变量初始化遵循的规则了。

第一段的规则依然有效,只是不健全。

  • 只有主动请求一个类,这个类才会初始化,仅包含静态变量,函数,等静态的东西.
  • 继承关系时,先初始化父类,后初始化子类.
  • 静态变量会按照声明的顺序先依次声明并设置为该类型的默认值,但不赋值为初始化的值.
  • 声明完毕后,再按声明的顺序依次设置为初始化的值,如果没有初始化的值就跳过.
  • 当初始化a.b=b.a时,暂停初始化a.b,设置当前类为b,跳到步骤3,并执行.
  • 当初始化b.plus = new a时,暂停初始化b.plus,实例化a并赋值给b.plus.
  • 当a的构造函数里需要获得b.a的值时,b.a还初始化并处于暂停初始化状态,直接取b.a的当前值,不再等待b.a初始化.
  • final,静态常量其实是遵循普通静态变量的初始化的,但是在编译时,编译器会将不可变的常量值在使用的地方替换掉.可以用java反编译工具查看.

static数据的初始化
加上static限定的字段,是所谓的类字段,也就是说这个字段的拥有者不是对象而是类。无论创建多少对象,static数据都只有一份。

类内总是先初始化static字段,再初始化一般字段。接着初始化构造器。但是如果不创建这个类的对象,那这个对象是不会进行初始化的,并且只执行一次。

如下面的代码,在staticinitialization类中,先初始化static table table = new table();,然后才去初始化table对象,不然是不会被初始化的。

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();
}

输出:

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)

显示的静态初始化(也就是静态块)
把多个初始化语句包在一个static花括号里,叫做静态块,其实就是把多个static合在一起写了,本质是一样的。只有首次创建对象或者首次访问类的字段时才会执行,而且仅仅一次。

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)
} 

输出:

inside main()
cup(1)
cup(2)
f(99)

非静态实例初始化
这个没什么好讲的,就是普通初始化,按顺序执行,可以多次执行。

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网