Java——静态字段和实例字段的初始化说明

我们都知道,在Java语言中,有静态字段和实例字段,但是,它们两者之间的初始化是有区别的。

其中,需要说明的一点就是:静态字段由类调用,实例字段由对象调用!!!

1. 静态字段

static 静态字段 / 静态变量 的初始化过程,由Java虚拟机JVM加载类后,自动进行静态字段初始化。

①静态字段的默认初始化:静态字段设置为其类型的默认值。

②静态字段的声明初始化:静态字段设置为声明时的初始化值。

③静态字段的静态块初始化:依次调用静态块进行初始化。

从源程序的角度看,静态字段以上三种初始化的顺序:

①首先进行默认初始化。

②然后根据声明初始化、静态块初始化这两者在程序中的顺序来依次进行!!!(两者谁先谁后是不一定的)

2. 实例字段 

实例字段 / 实例变量 的初始化过程,由new进行实例初始化。

①实例字段的默认初始化:实例字段设置为其类型的默认值。

②实例字段的声明初始化:实例字段设置为声明时的初始化值。

③实例字段的实例构造方法初始化:根据实例构造方法签名,调用实例构造方法进行初始化。

从源程序的角度看,实例字段以上三种初始化的顺序:

①首先必须进行默认初始化。

②然后进行声明初始化。

③最后进行实例构造方法的初始化。

因为实例字段相对来说,比较好理解,所以我们在这里重点对静态字段的初始化进行讲解!!!

我们依次来看下面的五个程序!!!👇👇👇 

Program Ⅰ: (没有静态块,静态变量的声明初始化的顺序不同)

class Test1 {
	public Test1() {
		System.out.println("Test1实例构造函数之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1实例构造函数之后 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	public static void main(String[] args) {
		System.out.println("最后的结果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅰ: 

Program Analysis Ⅰ:

按此顺序初始化静态变量:默认初始化→声明初始化 

默认初始化:静态变量按照声明的顺序依次设置为该类型的默认值。

声明初始化:静态变量按声明的顺序依次设置为声明初始化的值,如果没有声明初始化就跳过。 

静态字段初始化流程如下:

1. 默认初始化:类被加载后,首先静态字段会进行默认初始化。结果:t=null,a=0,b=0

2. 声明初始化:①首先进行静态字段t的声明初始化,创建Test1的实例,调用实例构造方法,执行之后的结果:a=1,b=1

                          ②然后进行静态字段a和b的声明初始化,因为静态字段a没有声明初始化,所以就跳过,并执行Test.a++,                     此时a=1;但是静态字段b由声明初始化,结果b=10。(大家对照这个流程,看一下上面的代码和运行结果)

 

Program Ⅱ:(没有静态块,静态变量的声明初始化的顺序不同)

class Test1 {
	public Test1() {
		System.out.println("Test1实例构造函数之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1实例构造函数之后 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static int a;
	public static int b=10;
        public static Test1 t=new Test1();
	public static void main(String[] args) {
		System.out.println("最后的结果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅱ: 

Program Analysis Ⅱ:

按此顺序初始化静态变量:默认初始化→声明初始化 

默认初始化:静态变量按照声明的顺序依次设置为该类型的默认值。

声明初始化:静态变量按声明的顺序依次设置为声明初始化的值,如果没有声明初始化就跳过。 

静态字段初始化流程如下:

1. 默认初始化:类被加载后,首先静态字段会进行默认初始化。结果:t=null,a=0,b=0。

2. 声明初始化:①首先进行静态字段a和b的声明初始化,因为静态字段a没有声明初始化,所以就跳过,结果还是a=0;但                     静态字段b有声明初始化,所以结果是b=10。

                         ②然后再进行静态字段t的声明初始化,创建Test1的实例,调用实例构造方法,Test.a++,Test.b++,执行                     之后的结果是a=1,b=11。(大家对照这个流程,看一下上面的代码和运行结果)

 

Program Ⅲ:(有静态块,静态块定义在声明初始化语句之后)

class Test1 {
	public Test1() {
		System.out.println("Test1实例构造函数之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1实例构造函数之后 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	static {
		a=20;
		System.out.println("static静态代码块1之后 a="+Test.a+",b="+Test.b);
	}
	static {
		b=30;
		System.out.println("static静态代码块2之后 a="+Test.a+",b="+Test.b);
	}
	public static void main(String[] args) {
		System.out.println("最后的结果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅲ:

Program Analysis Ⅲ:

按此顺序初始化静态变量:默认初始化→声明初始化→静态代码块初始化

默认初始化:静态变量按照声明的顺序依次设置为该类型的默认值。

声明初始化:静态变量按声明的顺序依次设置为声明初始化的值,如果没有声明初始化就跳过。 

静态代码块初始化:按照静态代码块的顺序依次设置静态字段的值。

静态字段初始化流程如下:

1. 默认初始化:类被加载后,首先静态字段会进行默认初始化。 结果:t=null,a=0,b=0。

2. 声明初始化:①首先进行静态字段t的声明初始化,创建Test1的实例,调用实力构造方法,执行之后的结果是a=1,b=1

                          ②进行静态字段a和b的声明初始化,因为静态字段a没有声明初始化,所以就跳过,结果还是a=1;但是静                    态字段b有声明初始化,所以结果是b=10。

3. 静态代码块初始化:①首先执行静态代码块1,对静态字段a进行静态块初始化,结果是a=20,b=10。

                                     ②然后执行静态代码块2,对静态字段b进行静态块初始化,结果是a=20,b=30。(大家对照这个流程,看一下上面的代码和运行结果)

 

Program Ⅳ:(有静态块,静态块定义在声明初始化语句之前)

class Test1 {
	public Test1() {
		System.out.println("Test1实例构造函数之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1实例构造函数之后 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	static {
		a=20;
		System.out.println("static静态代码块1之后 a="+Test.a+",b="+Test.b);
	}
	static {
		b=30;
		System.out.println("static静态代码块2之后 a="+Test.a+",b="+Test.b);
	}
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	public static void main(String[] args) {
		System.out.println("最后的结果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅳ:

Program Analysis Ⅳ:

按此顺序初始化静态变量:默认初始化→静态代码块初始化→声明初始化

默认初始化:静态变量按照声明的顺序依次设置为该类型的默认值。

静态代码块初始化:按静态块的顺序依次设置静态字段的值。 

声明初始化:静态变量按声明的顺序依次设置为声明初始化的值,如果没有声明初始化就跳过。

静态字段初始化流程如下:

1. 默认初始化:类被加载后,首先静态字段会进行默认初始化。 结果:t=null,a=0,b=0。

2. 静态代码块初始化:①首先执行静态代码块1,对静态字段a进行静态块初始化,结果是a=20,b=0。

                                     ②然后执行静态代码块2,对静态字段b进行静态块初始化,结果是a=20,b=30。

3. 声明初始化:①首先进行静态字段t的声明初始化,创建Test1的实例,调用实例构造方法,执行后的结果是a=21,b=31

                          ②然后进行静态字段a和b的声明初始化,因为静态字段a没有声明初始化,所以就跳过,结果还是a=21;                      但是静态字段b有声明初始化,所以结果是b=10。(大家对照这个流程,看一下上面的代码和运行结果)

 

Program Ⅴ:(有静态块,声明初始化语句在两个静态块定义之间)

class Test1 {
	public Test1() {
		System.out.println("Test1实例构造函数之前 a="+Test.a+",b="+Test.b);
		Test.a++;
		Test.b++;
		System.out.println("Test1实例构造函数之后 a="+Test.a+",b="+Test.b);
	}
}
public class Test {
	static {
		a=20;
		System.out.println("static静态代码块1之后 a="+Test.a+",b="+Test.b);
	}
	public static Test1 t=new Test1();
	public static int a;
	public static int b=10;
	static {
		b=30;
		System.out.println("static静态代码块2之后 a="+Test.a+",b="+Test.b);
	}
	public static void main(String[] args) {
		System.out.println("最后的结果:a="+Test.a+",b="+Test.b);
	}
}

Program Output Ⅴ:

Program Analysis Ⅴ:

按此顺序初始化静态变量:默认初始化→静态代码块1初始化→声明初始化→静态代码块2初始化

默认初始化:静态变量按照声明的顺序依次设置为该类型的默认值。

静态代码块初始化:按静态块的顺序依次设置静态字段的值。 

声明初始化:静态变量按声明的顺序依次设置为声明初始化的值,如果没有声明初始化就跳过。

静态字段初始化流程如下:

1. 默认初始化:类被加载后,首先静态字段会进行默认初始化。 结果:t=null,a=0,b=0。

2. 静态代码块1初始化:对静态字段a进行静态块初始化,结果a=20,b=0。

3. 声明初始化:①首先进行静态字段t的声明初始化,创建Test1的实例,调用实例构造方法,执行之后结果是a=21,b=1。

                          ②然后进行静态字段a和b的声明初始化,因为静态字段a没有声明初始化,所以就跳过,结果还是a=21;                      但是静态字段b有声明初始化,所以结果是b=10。

4. 静态代码块2初始化:对静态字段b进行静态块初始化,结果a=21,b=30。(大家对照这个流程,看一下上面的代码和运行结果)


根据上面这五个Java小程序,大家可能觉得比较多,看起来不舒服,但是静态字段这部分内容还是很重要的!!!

所以希望大家可以耐心的去理解每一个程序代码,对我们后面的Java知识的学习还是有很大帮助的!!!😊😊😊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章