初始化详细顺序

静态初始化

当一个类的静态方法/静态域被首次访问时,该类被加载,此时静态初始化的所有动作被执行,静态初始化只在类对象首次加载的时候进行一次。

/* 该例子证明了静态域被首次访问时,该类被加载,静态初始化的动作被执行了,且只会进行一次,
非静态初始化的方法没有被执行。*/

class Dog{
    static String className="dog";
    static String name=setName();
    String say=setSay();

    static String setName(){
        System.out.println("静态");
        return "哈士奇";
    }

    String setSay(){
        System.out.println("非静态");
        return "汪汪汪";
    }
    
    Dog(){
        System.out.println("Dog Constructor");
    }
}

public class Initialize {
    public static void main(String[] args) {
        System.out.println(Dog.className);
        System.out.println(Dog.name);
    }
}

/* out
静态
dog
哈士奇
*/

非静态初始化

非静态初始化的动作在创建对象时(实例化)被执行。

1.new Dog()创建对象时,在堆上会为该对象分配足够的存储空间
2.这块存储空间被清零(初始化成二进制的零,即基本类型数据初始化为0,对象引用初始化成null)
3.开始执行非静态字段定义处的初始化动作
4.执行构造器

/* 可以看到,new Dog();创建对象时,静态初始化也执行了,因为构造器实际也是static方法,
只不过它的static关键字没有被显式的表达出来。
该例证明了创建对象时,类会先进行静态初始化动作,之后进行非静态初始化动作,最后执行构造器,
非静态初始化动作在每一次创建对象时都需要执行。
步骤2、3在后面证明。
*/
class Dog{
    static String name=setName();
    String say=setSay();

    static String setName(){
        System.out.println("静态");
        return "哈士奇";
    }

    String setSay(){
        System.out.println("非静态");
        return "汪汪汪";
    }

    Dog(){
        System.out.println("Dog Constructor");
    }
}

public class Initialize {
    public static void main(String[] args) {
        new Dog();
        new Dog();
    }
}

/* out
静态
非静态
Dog Constructor
非静态
Dog Constructor
*/

涉及继承的初始化

  1. 在加载子类的过程中,编译器注意到它有一个基类(这是由关键字extends得知的),于是它继续进行加载(去加载基类)。不管你是否打算产生一个该基类的对象,这都要发生。
  2. 如果该基类还有其自身的基类,那么第二个基类就会被加载,如此类推。接下来根基类中的static初始化即会被执行,然后是下一个导出类,以此类推。
  3. 在所有静态字段初始化结束后,必要的类都已经加载完毕,对象就可以被创建了。首先,对象中所有的基本类型都会被设为默认值,对象引用被设为null——这是通过将对象内存设为二进制零值(上面说到的存储空间被清零)而一举生成的。
  4. 然后,从基类开始向下下执行,按照非静态字段初始化的顺序,先执行非静态初始化的动作,最后调用构造器,之后按这个顺序向下执行它的导出类,以此类推。
/*
该例证明了初始化的顺序:
1.先执行静态字段初始化的动作
2.在非静态字段初始化与构造器调用前,先给对象分配存储空间,并将存储空间清零(初始化成二进制的零),
所以可以看到Animal的构造器调用了被覆盖后的print()方法输出的结果是"dog.print(): 0" 而
不是 "dog.print(): 1"
3.在存储空间分配结束后,才从基类开始向下依次执行初始化,顺序为先执行非静态字段初始化,然后调用构
造器,然后向下初始化它的导出类,以此类推。
*/
class Animal{
    static String animalName = setAnimalName();

    void print(){
        System.out.println("animal.print()");
    }

    static String setAnimalName(){
        System.out.println("动物");
        return "Animal";
    }


    Animal(){
        print();
        System.out.println("Animal Constructor");
    }
}

class Mammalia extends Animal{
    static private String mammaliaName=setMammaliaName();
    private String mean=setMean();

    static String setMammaliaName(){
        System.out.println("哺乳动物");
        return "Mammalia";
    }

    String setMean(){
        System.out.println("母乳喂养");
        return "母乳喂养";
    }

    Mammalia(){
        System.out.println("Mammalia Constructor");
    }
}

class Dog extends Mammalia{
    int i=1;
    static String name=setName();
    String say=setSay();

    @Override
    void print() {
        System.out.println("dog.print(): "+i);
    }

    static String setName(){
        System.out.println("狗");
        return "哈士奇";
    }

    String setSay(){
        System.out.println("叫声");
        return "汪汪汪";
    }

    Dog(){
        System.out.println("Dog Constructor");
    }
}

public class Initialize {
    public static void main(String[] args) {
        new Dog();
    }
}

/* out
动物
哺乳动物
狗
dog.print(): 0
Animal Constructor
母乳喂养
Mammalia Constructor
叫声
Dog Constructor
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值