类的初始化顺序

先上一段代码:

父类:

package demo;

public class Insect {

 private int i = 9;
 protected int j;
 Insect() {
   System.out.println("i = " + i + ", j = " + j);
   j = 39;
 }
 private int p=print(" Insect.p initialized");
 private static int x1 =print("static Insect.x1 initialized");
 public static int print(String s) {
   System.out.println(s);
   return 47;
 }
 public static void dd()
 {
     System.out.println("aa ");
 }
}


子类:

package demo;

public class Beetle extends Insect {
private int k = print("Beetle.k initialized");
 public Beetle() {
   System.out.println("k = " + k);
   System.out.println("j = " + j);
 }
 public static void dd()
 {
     System.out.println("dd ");
 }
 private static  int x2 = print("static Beetle.x2 initialized");
 public static void main(String[] args) {
   System.out.println("Beetle constructor");
   Beetle b = new Beetle();
   
 }
}


输出结果:

static Insect.x1 initialized

static Beetle.x2 initialized

Beetle constructor
 Insect.p initialized
i = 9, j = 0
Beetle.k initialized
k = 47
j = 39

 

分析过程:

       当我们运行此程序的时候,主线程启动,编译器开始寻找Beetle.class这个类,找到后,开始加载这个类,加载的过程中发现有extends关键字,所以编译器开始去加载父类insect.class(如果在加载insect.class的过程中,发现它还有基类,则先加载它的基类,以此类推)。

         此时(加载insect类时),insect的静态代码将被执行(静态成员的初始化),所以此时打印出:static Insect.x1 initialized;当insect的静态代码执行之后,Beetle的静态代码开始执行,所以打印出:static Beetle.x2 initialized。

        到现在为止,所有基类和当前类的静态初始化动作已经执行完成了,可以初始化对象了

        接下来,从main函数开始,执行第一句,打印出Beetle constructor;

       下面执行Beetle b = new Beetle(),首先为Beetle分配内存空间,初始化以下三个动作:

(1)       对于 char,short,byte,int,long,float,double等基本数据类型的变量会初始化为0,boolean类型初始化为false

(2)       对于引用类型的变量,会初始化为null

(3)       如果没有显示的定义构造器,则编辑器会自动创建一个无参的构造器,反之,不会。


       在Beetle内的代码执行之前,首先会调用基类的构造器,在基类的构造器内的代码执行之前,首先要对基类的非静态成员初始化。此时打印出:Insect.p initialized,当执行后,基类的构造函数里面的代码开始执行,所以打印出:i = 9, j = 0;此时j被初始化为39。

      当基类的构造器代码执行之后,首先要对Beetle的非静态成员进行显示的初始化,此时K被初始化为47,并且打印出:Beetle.k initialized;等初始化完成后,Beetle构造器里的代码开始执行,所以打印出:K=47;J=39。现在,程序终于分析完了!

       值得注意的是:静态成员初始化是从最顶层的类开始的,因为子类成员的初始化可能回用到基类的成员。

所以类加载以及初始化的顺序是:类的静态成员初始化分配内存(有父类的先父类,然后自己)->然后main方法执行->类初始化{类非静态成员的初始化,然后执行构造器(有父类的先给父类的非静态成员初始化,然后父类的构造器)}


易错的地方:当执行到子类的非静态成员初始化时,执行这一句:private int k = print("Beetle.k initialized")时,会调用到父类的print函数,将参数Beetle.k initialized传给 print(),并且返回47给k。注意:此时把值返回给调用它的地方,即k。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值