Java初始化规则都不懂,搞什么开发!

这个教程,咱们来对Java中设计到的初始化规则,或者说初始化顺序,来做一下汇总,这里我基本上把Java中,默认初始化,静态成员初始化,非静态成员初始化,静态代码块,非静态代码块,以及继承中所涉及到的初始化,都涵盖全了。希望你看到这个教程,能有所收获。(๑´ڡ`๑) 


默认初始化

在Java中,一个类的数据成员(成员变量)如果没有指定初始化,那么Java会对其执行默认初始化。
基本类型初始化默认值为0,boolean为false,字符串或者对象引用初始化为null。这部分比较简单,看下面这个小列子,相信你应该能直接看出来最后运行的结果。(<_<) 


public class InitialValues {
    boolean t;
    char c;
    short s;
    int i;
    long l;
    float f;
    double d;
    String str;
    InitialValues reference;

    void printInitialValues() {
        System.out.printf("%-10s %-5s\n", "boolean:", t);
        System.out.printf("%-10s %-5s\n", "char:", c);
        System.out.printf("%-10s %-5s\n", "short:", s);
        System.out.printf("%-10s %-5s\n", "int:", i);
        System.out.printf("%-10s %-5s\n", "long:", l);
        System.out.printf("%-10s %-5s\n", "float:", f);
        System.out.printf("%-10s %-5s\n", "double:", d);
        System.out.printf("%-10s %-5s\n", "String:", str);
        System.out.printf("%-10s %-5s\n", "reference:", reference);
    }

    public static void main(String[] args) {
        InitialValues iv = new InitialValues();
        iv.printInitialValues();
    }
}


// Output
----------------
boolean:   false
char:           
short:     0    
int:       0    
long:      0    
float:     0.0  
double:    0.0  
String:    null
reference: null


非静态成员初始化顺序

在一个类中,非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序。来看下面这个小程序,这里的类,我都用的通用的无实际意义的类,这样能让咱们把注意力放在代码逻辑上。这个小程序,我给你提点要求:你捋一下代码的逻辑,看看能不能直接写出来最后的运行结果。完了把你写的结果和我后面给你的答案对比一下,看看能不能搞对。最后你自己最好能敲敲程序运行一下。( •̀⊿•́)ง



class XXX {
    XXX(String s){ System.out.println("XXX > " + s); }
}

class AAA {
    XXX x001 = new XXX("001");
    AAA() {
        System.out.println("AAA");
        XXX x004 = new XXX("004");
    }
    XXX x002 = new XXX("002");
    void fff() { System.out.println("fffffffff"); }
    XXX xxx003 = new XXX("003");
}

public class Initialization {
    public static void main(String[] args) {
        AAA aaa = new AAA();
        aaa.fff();
    }
}


// Output
---------
XXX > 001
XXX > 002
XXX > 003
AAA
XXX > 004
fffffffff


静态成员初始化及对象的创建过程

以名为
YYY的类举例:
  • 当该类的静态方法(包括main()和构造器,构造器实际上也是静态方法)或者静态成员被调用或访问时,Java虚拟机将载入类所对应的YYY.class文件,并创建其Class对象,然后该类所有的静态成员将执行初始化。并且静态成员初始化只执行这一次。
  • 静态初始化完成后,该类就做好了创建对象的准备。当调用new YYY()创建对象的时候,首先在堆内存上为YYY对象分配空间,然后执行默认初始化(基本类型初始化为0,引用类型初始化为null)。
  • 之后,按照非静态成员定义顺序,进行指定初始化。
  • 最后执行构造器,完成对象的创建。
还是和上面同样的要求,先捋代码逻辑,再手写结果。 (`・ω・´)ゞ



class XXX {
    XXX(String s){ System.out.println("XXX > " + s); }
    void xox(String s){ System.out.println("xox : " + s); }
}

class AAA {
    XXX x001 = new XXX("001");
    static XXX x002 = new XXX("002");
    AAA() {
        System.out.println("AAA");
        x002.xox("002");
    }
    void aaa() { System.out.println("aaa"); }
}

class BBB {
    static XXX x003 = new XXX("003");
    XXX x004 = new XXX("004");
    BBB(){
        System.out.println("BBB");
        x004.xox("004");
    }
    void bbb(){System.out.println("bbb");}
}

public class Initialization {
    public static void main(String[] args) {
        System.out.println("*********");
        new AAA();
        System.out.println("=========");
        new BBB();
        a002.aaa();
        b002.bbb();
    }

    AAA a001 = new AAA();
    static AAA a002 = new AAA();
    static AAA a003= new AAA();
    BBB b001 = new BBB();
    static BBB b002 = new BBB();
    static BBB b003 = new BBB();
}


// Output
---------
XXX > 002
XXX > 001
AAA
xox : 002
XXX > 001
AAA
xox : 002
XXX > 003
XXX > 004
BBB
xox : 004
XXX > 004
BBB
xox : 004
*********
XXX > 001
AAA
xox : 002
=========
XXX > 004
BBB
xox : 004
aaa
bbb


静态块代码初始化

其实,整个static { 静态代码块 可以看作是一个静态成员。当一个类需要执行静态初始化时,该类中的静态成员初始化和静态代码块,会按照先后定义的顺序执行。当然,这个流程也是就执行这一次。ღ⊙□⊙╱ 还是老要求......



class XXX {
    XXX(String s){ System.out.println("XXX > " + s); }
}

class AAA {
    XXX x001 = new XXX("001");
    static XXX x002 = new XXX("002");
    static XXX x003, x004;
    static {
        System.out.println("*********");
        x003 = new XXX("003");
        x004 = new XXX("004");
        XXX x005 = new XXX("005");
        System.out.println("=========");
        /**System.out.println(x006);*/
    }
    static XXX x006 = new XXX("006");
    XXX x007 = new XXX("007");
    AAA() { System.out.println("AAA"); }
}

public class Initialization {
    static AAA aaa = new AAA();
    public static void main(String[] args) {
        new AAA();
    }
}


// Output
---------
XXX > 002
*********
XXX > 003
XXX > 004
XXX > 005
=========
XXX > 006
XXX > 001
XXX > 007
AAA
XXX > 001
XXX > 007
AAA

假如把上面/**System.out.println(x006);*/注释掉的代码解除注释,再运行程序,会发生什么情况?


非静态代码块初始化

{
非静态代码块 },可以看作一个非静态成员。涉及非静态初始化,也会执行它。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。
稍微修改下上面的例子,把静态代码块前面的static关键字去掉,并把里面的注释行释放,并添加一行打印语句,如下,对比两个例子输出结果。(=•̀口•́=)



class XXX {
    XXX(String s){ System.out.println("XXX > " + s); }
}

class AAA {
    XXX x001 = new XXX("001");
    static XXX x002 = new XXX("002");
    static XXX x003, x004;
    {
        System.out.println("*********");
        x003 = new XXX("003");
        x004 = new XXX("004");
        XXX x005 = new XXX("005");
        System.out.println("=========");
        System.out.println(x006);
        System.out.println(x001);
    }
    static XXX x006 = new XXX("006");
    XXX x007 = new XXX("007");
    AAA() { System.out.println("AAA"); }
}

public class Initialization {
    static AAA aaa = new AAA();
    public static void main(String[] args) {
        new AAA();
    }
}


// Output
-------------
XXX > 002
XXX > 006
XXX > 001
*********
XXX > 003
XXX > 004
XXX > 005
=========
XXX@1540e19d
XXX@677327b6
XXX > 007
AAA
XXX > 001
*********
XXX > 003
XXX > 004
XXX > 005
=========
XXX@1540e19d
XXX@14ae5a5
XXX > 007
AAA


继承中涉及的初始化

大的原则是:没有父类,就没子类。初始化,当然要先初始化父类,再初始化子类。
继承中如果同时涉及到静态初始化和非静态初始化。初始化的执行流程分两步走:
(1)先执行静态初始化。且先静态初始化父类,然后再静态初始化子类。(这一步同样就执行一次)
(2)父类执行非静态初始化,然后调用构造方法。接着子类执行非静态初始化,然后调用构造方法。接着下一个子类......以此类推到最后一个子类。 _(•̀ω•́ 」∠)_



class XXX {
    XXX(String s){ System.out.println("XXX > " + s); }
}

class AAA {
    XXX x001 = new XXX("001");
    static XXX x002 = new XXX("002");
    AAA() {
        System.out.println("AAA");
    }
    {
        System.out.println("*********");
        XXX x003 = new XXX("003");
    }
    static XXX x004;
    static {
        System.out.println("=========");
        x004 = new XXX("004");
    }
    static XXX x005 = fff("005");
    static XXX fff(String s) {
        System.out.println("fffffffff");
        return new XXX(s);
    }
}

class BBB extends AAA {
    static XXX x006 = new XXX("006");
    XXX x007= new XXX("007");
    {
        System.out.println("+++++++++");
        XXX x008 = new XXX("008");
    }
    static XXX x009;
    static {
        System.out.println("$$$$$$$$$");
        x009 = new XXX("009");
    }
    BBB(){
        System.out.println("BBB");
    }
    static XXX x010 = fff("010");
}

public class Initialization {
    public static void main(String[] args) {
        new BBB();
        new BBB();
    }
}


// Output
---------
XXX > 002
=========
XXX > 004
fffffffff
XXX > 005
XXX > 006
(9个$符号,博客有问题,不显示9个$)
XXX > 009
fffffffff
XXX > 010
XXX > 001
*********
XXX > 003
AAA
XXX > 007
+++++++++
XXX > 008
BBB
XXX > 001
*********
XXX > 003
AAA
XXX > 007
+++++++++
XXX > 008
BBB

拓展一下,假如把上面的父类AAA改为抽象类,运行结果还一样吗?自己求证一下吧。
好,暂时先写这么多,希望多多少少帮到了你点什么,后面我想到有需要补充的,我再更新帖子吧。✿✿ヽ(゚▽゚)ノ✿

==========================================================

有条件的小伙伴,可以给打赏点儿支持下,给我些鼓励继续写下去。  (๑´ㅂ`๑́)و✧



  • 17
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值