java静态域 初始化_java类静态域、块,非静态域、块,构造函数的初始化顺序

本文详细探讨了Java中类的初始化顺序,包括静态变量、静态初始化块、变量、初始化块和构造器。在非继承情况下,初始化顺序是静态变量、静态初始化块、变量、初始化块、构造器。而在继承场景下,子类的静态部分在父类的实例部分之前初始化。同时,静态变量和静态初始化块、变量和初始化块的初始化顺序取决于它们在类中的定义顺序。代码示例展示了这些规则,并强调静态代码块在类加载时执行,非静态代码块在创建对象时执行。
摘要由CSDN通过智能技术生成

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是

(静态变量、静态初始化块)>(变量、初始化块)>构造器。

我们也可以通过下面的测试代码来验证这一点:

Java代码

1 public classInitialOrderTest {2 //静态变量

3 public static String staticField = "静态变量";4 //变量

5 public String field = "变量";6 //静态初始化块

7 static{8 System.out.println(staticField);9 System.out.println("静态初始化块");10 }11 //初始化块

12 {13 System.out.println(field);14 System.out.println("初始化块");15 }16 //构造器

17 publicInitialOrderTest() {18 System.out.println("构造器");19 }20 public static voidmain(String[] args) {21 newInitialOrderTest();22 }23 }

运行以上代码,我们会得到如下的输出结果:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

静态变量

静态初始化块

变量

初始化块

构造器

View Code

这与上文中说的完全符合。

那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:

Java代码

1 classParent {2 //静态变量

3 public static String p_StaticField = "父类--静态变量";4 //变量

5 public String p_Field = "父类--变量";6 //静态初始化块

7 static{8 System.out.println(p_StaticField);9 System.out.println("父类--静态初始化块");10 }11 //初始化块

12 {13 System.out.println(p_Field);14 System.out.println("父类--初始化块");15 }16 //构造器

17 publicParent() {18 System.out.println("父类--构造器");19 }20 }21 public class SubClass extendsParent {22 //静态变量

23 public static String s_StaticField = "子类--静态变量";24 //变量

25 public String s_Field = "子类--变量";26 //静态初始化块

27 static{28 System.out.println(s_StaticField);29 System.out.println("子类--静态初始化块");30 }31 //初始化块http://ini.iteye.com/

32 {33 System.out.println(s_Field);34 System.out.println("子类--初始化块");35 }36 //构造器

37 publicSubClass() {38 System.out.println("子类--构造器");39 }40 //程序入口

41 public static voidmain(String[] args) {42 newSubClass();43 }44 }

运行一下上面的代码,结果马上呈现在我们的眼前:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

父类--静态变量

父类--静态初始化块

子类--静态变量

子类--静态初始化块

父类--变量

父类--初始化块

父类--构造器

子类--变量

子类--初始化块

子类--构造器

View Code

现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,

实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?

是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。

我们以静态变量和静态初始化块为例来进行说明。 同样,我们还是写一个类来进行测试:

Java代码

1 public classTestOrder {2 //静态变量

3 public static TestA a = newTestA();4 //静态初始化块

5 static{6 System.out.println("静态初始化块");7 }8 //静态变量

9 public static TestB b = newTestB();10 public static voidmain(String[] args) {11 newTestOrder();12 }13 }14 classTestA {15 publicTestA() {16 System.out.println("Test--A");17 }18 }19 classTestB {20 publicTestB() {21 System.out.println("Test--B");22 }23 }

运行上面的代码,会得到如下的结果:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

Test--A

静态初始化块

Test--B

View Code

大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,

这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。

了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。

测试函数:

1 public classTestStaticCon {2 public static int a = 0;3 static{4 a = 10;5 System.out.println("父类的非静态代码块在执行a=" +a);6 }7 {8 a = 8;9 System.out.println("父类的非静态代码块在执行a=" +a);10 }11 publicTestStaticCon() {12

13 this("a在父类带参构造方法中的值:" + TestStaticCon.a); //调用另外一个构造方法

14 System.out.println(a);15 System.out.println("父类无参构造方法在执行a=" +a);16 }17 publicTestStaticCon(String n) {18 System.out.println(n);19 System.out.println(a);20 }21 public static voidmain(String[] args) {22 TestStaticCon tsc = null;23 System.out.println("!!!!!!!!!!!!!!!!!!!!!");24 tsc = newTestStaticCon();25 }26 }

运行结果:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

父类的非静态代码块在执行a=10

!!!!!!!!!!!!!!!!!!!!!父类的非静态代码块在执行a=8a在父类带参构造方法中的值:10

8

8父类无参构造方法在执行a=8

View Code

结论:静态代码块是在类加载时自动执行的,非静态代码块是在创建对象时自动执行的代码,不创建对象不执行该类的非静态代码块。且执行顺序为静态代码块------非静态代码块----构造函数。

扩展:静态代码块  与  静态方法:

一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;

需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的.

两者的区别就是:静态代码块是自动执行的;  静态方法是被调用的时候才执行的.

作用:静态代码块可用来初始化一些项目最常用的变量或对象;静态方法可用作不创建对象也可能需要执行的代码

阿里笔试题:

求下面这段代码的输出:

1 public classTest1 {2

3 public static int k = 0;4 public static Test1 t1 = new Test1("t1");5 public static Test1 t2 = new Test1("t2");6 public static int i = print("i");7 public static int n = 99;8 public int j = print("j");9 {10 print("构造块");11 }12

13 static{14 print("静态块");15 }16

17 publicTest1(String str){18 System.out.println((++k)+":"+str+" i="+i+" n="+n);19 ++i;++n;20 }21

22 public static intprint(String str){23 System.out.println((++k)+":"+str+" i="+i+" n="+n);24 ++n;25 return ++i;26 }27

28 public static voidmain(String[] args) {29 Test1 t = new Test1("init");30 //System.out.println("Test1.t1.j = " + Test1.t1.j);31 //System.out.println("Test1.t2.j = " + Test1.t2.j);

32 }33

34 }

运行结果:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1:j i=0 n=0

2:构造块 i=1 n=1

3:t1 i=2 n=2

4:j i=3 n=3

5:构造块 i=4 n=4

6:t2 i=5 n=5

7:i i=6 n=6

8:静态块 i=7 n=99

9:j i=8 n=100

10:构造块 i=9 n=101

11:init i=10 n=102

//Test1.t1.j = 1//Test1.t2.j = 4

View Code

你猜到结果了吗?自己运行下看看。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值