• java基础之——类的初始化顺序


    由浅入深,首先,我们来看一下,一个类初始化有关的都有些啥米:

      静态成员变量、静态代码块、普通成员变量、普通代码块、构造器。(成员方法?貌似跟初始化没有啥关系)

    现在我们来看看她们的初始化顺序,

      从性质上来说,静态的代表的是一个类的属性,普通的是一个对象的属性,“皮之不存,毛将焉附”,没有类,就没法谈对象,所以静态的必须先初始化。

    那么静态成员变量与静态代码块之间又是什么关系呢?

      做了个实验,发现静态成员变量与静态代码块谁放前面谁先执行,但是!!!!注意!!!!这里说的是“执行”是指的把sx=10,这个10赋给sx,而不是sx的初始化,在实验2里在代码块中打断点,可以发现这个时候sx已经被初始化为0,这里我是这样理解:既然在初始化这个类(或对象)的成员了,那说明已经给它分配好内存了,int分配好内存后默认值为0(基础类型的默认值有false,0,null),不知道这么理解对不对。所以最终的结论是,先初始化成员变量为默认值,然后根据成员变量与代码块的先后顺序进一步初始化。

    实验代码如下:

    //实验1
    private
    static int sx = 10; static{ System.out.println("execute static block"); } 与
    //实验2
    static{ System.out.println("execute static block"); } private static int sx = 10;

      接着说,普通成员变量与普通代码块和静态的一个道理,就不累述了。

    那么构造器与普通成员变量和普通代码块的关系呢?

      这个我是通过实验得了这么个结论,是成员变量的"=xxx"(和成员变量初始化为默认值区分)和代码块先执行,然后再执行构造器中的。(实验代码最后一并贴出)

    ok到这里为止,一个类的我们简单的说完了,那么类还有继承呢,子类和父类结合到一起的时候又是什么一个顺序呢?

    其实挺简单的,子类继承自父类,可以使用父类的非private成员,所以,在在初始化子类之前肯定是要先初始化父类。

    最终的顺序是:

    父类静态成员变量初始化为默认值—>

    子类静态成员变量初始化为默认值—>

    父类按出现的先后顺序执行静态成员变量的“=xxx”和静态代码块—>

    子类的按出现的先后顺序执行静态成员变量的“=xxx”和静态代码块—>

    父类普通成员变量初始化为默认值—>

    子类普通成员变量初始化为默认值—>

    父类按出现的先后顺序执行普通成员变量的“=xxx”和静态代码块—>

    父类执行构造函数—>

    子类的按出现的先后顺序执行普通成员变量的“=xxx”和静态代码块—>

    子类执行构造函数—>end

    实验代码:

    package abstractClass;
    
    @SuppressWarnings("unused")
    abstract class AbstractDemo {
        {
            System.out.println("execute super block,this.x="+this.x);
        }
        static{
            System.out.println("execute static super block,this.sx="+AbstractDemo.sx);
        }
        public static int SuperPS = 1;
        private static int sx = 1;
        private int x = 1;
    
        public AbstractDemo(){
            super();
            System.out.println("execute super constractor");
    //        this.print();
        }
        
        public abstract void print();
    }
    
    @SuppressWarnings("unused")
    class DemoImpl extends AbstractDemo{
        public static int PS = 10;
        private static int sx = 10;
        private int x = 10;   //从调试的结果来看,此处是在执行完super()之后执行,然后再接着执行构造器
        {
            System.out.println("execute block,this.x="+this.x);
        }
        static{
            System.out.println("execute static block,this.sx="+DemoImpl.sx);
        }
        public DemoImpl(int x){
            super();  //断点
            System.out.println("execute constractor");
            System.out.println("before init in constractor this.x="+this.x);
            this.x = x;
        }
        
        @Override 
        public void print(){
            System.out.println("this.x="+x);
        }
    }
    
    public class TestAbstractDemo{
        public static void main(String[] args) {
            new DemoImpl(100);
        }
    }

    实验结果:

    execute static super block,this.sx=0
    execute static block,this.sx=10
    execute super block,this.x=0
    execute super constractor
    execute block,this.x=10
    execute constractor
    before init in constractor this.x=10

    作者:苍枫露雨
             
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    写了一个抓飞信包的小工具
    Drools.Net Bug?
    论坛系统分析比较
    在线个人财务管理服务推荐:财客在线网络账本
    多站点的google analytics的使用心得
    FeedSky更新出现很大延时
    愚人节,中华民族的伟大梦想实现了
    Community Server 2008.5 SP2发布啦
    [已上传流程图]在线服务器状态监控预警软件推荐:网站保姆
    五一公司搬家记
  • 原文地址:https://www.cnblogs.com/chrischennx/p/3612295.html
Copyright © 2020-2023  润新知