Java类成员初始化顺序

成员初始化顺序

Java初始化顺序

Java初始化的原则是:保证成员在使用前都能得到初始化。

下面用代码来理解初始化的顺序:

public class Demo{
	public static void main(String[] args) {
		System.out.println("+++++++调用Main方法+++++++");
		new B();
		System.out.println("=======第二次初始化======");
		new B();
		System.out.println("+++++++结束Main方法+++++++");
	}
}
class A{
	public A(int i) {
		System.out.println("this is A"+i);
	}
}
class B_Father{
	A aa;
	{
		aa = new A(11);
		System.out.println("非静态初始化:"+aa);
	}
	public B_Father() {
		System.out.println("this is B_Father");
	}
	static A bb;
	static{
		bb = new A(22);
		System.out.println("静态初始化:"+bb);
	}
}
class B extends B_Father{
	A a;
	{
		a = new A(1);
		System.out.println("非静态初始化:"+a);
	}
	public B() {
		System.out.println("this is B");
	}
	static A b;
	static{
		b = new A(2);
		System.out.println("静态初始化:"+b);
	}
}

打印结果分析


在这里插入图片描述
拓展: 自动初始化
自动初始化发生在类的加载时期,如果知道jvm加载类的过程,在类进行初始化之前,自动初始化已经发生;这里的类初始化只包括指定值对类的初始化。
自动初始化是不会初始化局部变量的,下面例子说明未对局部变量初始化就是用,会抛出编译期错误:

class A{
	public void method(){
	//方法中定义的变量为局部变量
		int a;
		System.out.println(a);
	}
}
/*output:
Demo.java:5: 错误: 可能尚未初始化变量a
                System.out.println(a);
                                   ^
1 个错误*/

- 初始化的时机

当类被主动引用时,类便会获得初始化的时机,有以下四种:

  1. 使用new关键字创建对象
  2. 调用类中的静态成员
  3. Java反射获得class对象
  4. main方法所在的类

除了new关键字来创建一个对象,会导致类进行一次完整的初始化;其他的初始化时机只会引起Java类中的静态成员初始化。

public class Demo{
	public static void main(String[] args) throws Exception{
		System.out.println("+++++++调用Main方法+++++++");
		System.out.println("1.调用类中的静态成员,引起初始化:");
		A a = B.b;
		System.out.println("2.使用Java反射获得class对象的引用:");
		Class b = Class.forName("B");
		System.out.println("3.main方法所在的类:略");
		System.out.println("+++++++结束Main方法+++++++");
	}
}

打印结果分析


在这里插入图片描述
Tips: 这三种情况都有一个共同点,都是对类作用域进行操作,只需要初始化静态成员。

特殊情况,当类被动引用时,不会进行初始化:

  1. 调用类中的final常量
  2. 实例化对象数组
  3. 通过子类调用父类静态成员,只会初始化父类
public class Demo{
	public static void main(String[] args) throws Exception{
		System.out.println("+++++++调用Main方法+++++++");
		B b = new B();
		System.out.println("1.调用类中的常量。");
		int a = b.cc;
		System.out.println("2.数组来容纳对象");
		B[] bb = new B[10];		//这里只给bb分配空间,而不将类B对象放入,不会引起初始化
		System.out.println("3.调用父类中的静态变量,不会引起初始化");
		A aa = b.aa;
		System.out.println("+++++++结束Main方法+++++++");
	}
}

在这里插入图片描述

- 静态初始化的特殊性

Java中的static关键字定义静态变量,也有全局变量的说法,因为静态变量是属于类的,一个类无论实例化多少次,都静态变量都只占一份内存;Java中并没有全局变量,称它为全局变量不符合面向对象语言的多态性和封装特性。
static变量在类初始化中,只会初始化一次,除非我们直接调用静态变量。
在这里插入图片描述
静态初始化可以使用静态块来帮助静态变量初始化

static int a;
static{
	a = 10;
}

Tips: 静态块要么单独使用,要么只能和要初始化的变量绑定在一起。

- 指定值来初始化

指定值初始化的普遍方式有三种:

  1. 在定义时进行初始化
  2. 通过方法return来进行初始化
  3. 通过构造方法来进行初始化

对于静态变量,我们还可以使用静态块来初始化;非静态变量,我们可以使用类似静态块的方式初始化,也称实例初始化

拓展: 数组初始化

public class Demo{
	//1.利用for循环初始化
	Integer[] a1 = new Integer[5];
	for(int i = 0; i < a1.length; i++){
		a1[i] = i;
	}
	//2.聚集初始化
	Integer[] a2 = {1,2,3,4,5};
	//3.动态聚集初始化
	Integer[] a3 = new Integer[]{1,2,3,4,5};
}

有关例题解析

题 1 :分析打印结果

在这里插入图片描述
打印结果:YXYZ

解析:第一步初始化main方法所在的类 Z,因为没有静态方法,所以跳过 ;第二步,初始化类Z,先初始化父类 X 中的 非静态成员创建对象 Y并 打印一个 Y ,再调用父类构造方法,打印一个 X;最后初始化类 Z 中的非静态成员创建对象 Y 并 打印一个 Y,之后调用类 Z 的构造方法并 打印一个 Z

总结

  1. 本文只讲了成员变量的初始化,并没有说方法的初始化,我们只谈方法的调用,成员初始化可以通过打印查看到初始化轨迹,方法却无法直观看到,我们只能调用方法。
  2. 成员方法的初始化顺序:在成员变量之后初始化,遵循Java初始化的原则,static方法在普通方法之前。
  3. 构造方法是不是静态方法?
    如果说他是静态方法,那么他就不能调用非静态的方法了,反证,构造方法不是静态方法。
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

呆呆papa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值