java类的初始化与实例初始化

收获:对于java类初始化和实例初始化的思考。

public class Father{
	private int i = test();
	private static int j = method();
	
	static{
		System.out.print("(1)");
	}
	Father(){
		System.out.print("(2)");
	}
	{
		System.out.print("(3)");
	}
	
	public int test(){
		System.out.print("(4)");
		return 1;
	}
	public static int method(){
		System.out.print("(5)");
		return 1;
	}
}
public class Son extends Father{
	private int i = test();
	private static int j = method();
	static{
		System.out.print("(6)");
	}
	Son(){
		System.out.print("(7)");
	}
	{
		System.out.print("(8)");
	}
	public int test(){
		System.out.print("(9)");
		return 1;
	}
	public static int method(){
		System.out.print("(10)");
		return 1;
	}
	public static void main(String[] args) {
		Son s1 = new Son();
		System.out.println();
		Son s2 = new Son();
	}
}

运行结果:

类初始化和实例初始化

java程序初始化时,最先进行的是类初始化,然后再进行实例初始化。这也比较容易理解,先有类才有对象。

其次是先进行静态代码的初始化,再非静态代码的初始化,最后进行构造器代码的执行。

1. 类初始化

(1)一个类要创建实例需要先加载并初始化该类。其中,main方法所在的类需要先加载和初始化。

(2)一个子类要初始化需要先初始化父类

(3)java的类初始化,其实是执行了一个()方法。====

  • ()方法由静态类变量显式赋值代码静态代码块组成;
  • 静态类变量显示赋值代码和静态代码块代码从上到下顺序执行。即静态的代码按顺序执行
  • ()方法只执行一次。

2. 实例初始化过程

实例初始化其实是执行了()方法。

  • ()方法可能重载有多个,有几个构造器就有几个()方法;
  • ()由非静态实例变量显式赋值代码和非静态代码块、对应构造器代码组成;
  • 非静态实例变量显式赋值代码和非静态代码块,这些非静态代码,按照顺序由上到下执行,而对应的构造器代码最后执行
  • 每次创建实例对象,调用对应构造器,执行的就是对应的()方法;
  • ()方法的首行是super()或super(实参列表),即对应父类的方法。不论写不写super(),它都是存在的。

3. 方法的重写Override

(1)哪些方法不能被重写

  • final 方法
  • 静态方法
  • private等子类中不可见的方法

(2)对象的多态性

  • 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码。
  • 非静态方法默认的调用对象是 this
  • this 对象在构造器或者说()方法中,就是正在创建的对象

4. 进阶

(1)Override 和 Overload 的区别?

(2)Override 重写的要求?

(3)了解《JVM虚拟机规范》中关于和方法的说明、invokespecial指令

5. 例题解析

  1. main方法所在类是Son,所以先加载Son所在类;

  2. 由于子类初始化之前需要先初始化父类,所以先加载 Father, 而 Father 没有父类了,所以直接加载Father;

  3. 类加载过程,即执行()方法,执行静态的代码,并且这些静态的代码是按照从上到下执行的。因此,执行了(5)然后是(1);

  4. 父类加载完成后,开始加载子类。同样地,按顺序执行了(10)(6);

  5. 类加载完毕后,开始执行实例加载过程。同样地,实例化子类之前要先实例化父类。

  6. 实例化对象的过程,实质上是执行了()方法,于是按顺序执行非静态的代码。这里先执行的是

    private int i = test();
    

    实际上,非静态方法默认的调用对象是 this, 因此这句代码等同于:

    private int i = this.test();
    

    而 this 对象在构造器,或者说()方法中,就是正在创建的对象,也就是正在创建的Son对象,也就是调用了子类重写的test()方法。所以输出的应该是(9)。

  7. 执行完了test()方法,接着就是执行非静态代码块,输出了(3),最后执行构造方法里的代码,输出了(2)。

  8. 按同样的规则,输出了(9)(8)(7)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值