博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于静态块、静态属性、构造块、构造方法的执行顺序
阅读量:4055 次
发布时间:2019-05-25

本文共 3606 字,大约阅读时间需要 12 分钟。

总结:

1、类加载时,执行静态代码块和初始化静态变量。执行顺序跟代码顺序一致。

2、类实例化时,初始化变量、执行代码块、执行构造。其中初始化变量和代码块的顺序跟代码顺序一致。执行构造是在最后。

3、实例化子类时,会先调用父类的构造方法。调用构造方法之前,会先执行该类的代码块。

4、类只会加载一次。

5、静态变量或静态方法中如果调用构造,可以把构造当做一个普通方法来看。但会先执行一遍代码块。

 

下面是在网上找到的比较典型的例子,以此来说明

例一:

class A {    static {        System.out.println("A的静态块");    }    private static String staticStr = getStaticStr();    private String str = getStr();    {        System.out.println("A的实例块");    }        public A() {        System.out.println("A的构造方法");    }    private static String getStaticStr() {        System.out.println("A的静态属性初始化");        return null;    }    private String getStr() {        System.out.println("A的实例属性初始化");        return null;    }    public static void main(String[] args) {        new B();        new B();    }}class B extends A{    private static String staticStr = getStaticStr();    static {        System.out.println("B的静态块");    }    {        System.out.println("B的实例块");    }    public B() {        System.out.println("B的构造方法");    }    private String str = getStr();    private static String getStaticStr() {        System.out.println("B的静态属性初始化");        return null;    }    private String getStr() {        System.out.println("B的实例属性初始化");        return null;    }}

该段代码的执行结果为:

A的静态块

A的静态属性初始化
B的静态属性初始化
B的静态块
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法

由此可见,实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象。

接下来是加载顺序,当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,首先执行构造块(直接写在类中的代码块),然后执行构造方法。至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。


 

例二:

public class EXA {    private static EXA a = new EXA();      static {          System.out.println("父类--静态代码块");      }        public EXA() {          System.out.println("父类--构造函数");      }        {          System.out.println("父类--非静态代码块");      }        public static void main(String[] args) {        new EXC();        new EXC();    }}class EXC extends EXA {      private static EXC b = new EXC();      static {          System.out.println("子类--静态代码块");      }      {          System.out.println("子类--非静态代码块");      }        public EXC() {          System.out.println("子类--构造函数");      }}

该段代码的执行结果为:

父类--非静态代码块

父类--构造函数
父类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数

分析(非静态代码块即构造块):

首先要加载父类EXA,由于A的静态属性在静态块的前面,先初始化静态属性(new EXA())(父类--非静态代码块;父类--构造函数),然后是静态块(父类--静态代码块);

加载子类EXC,由于EXC的静态属性也在静态块的前面,先初始化静态属性(new EXC()),实例化子类对象的时候会先实例化父类,所以执行的顺序为(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数),然后是静态块(子类--静态代码块)

实例化父类EXA对象:父类--非静态代码块;父类--构造函数;

实例化子类EXC对象:子类--非静态代码块;子类--构造函数;

第二个new EXC():因为父类和子类都已加载,只需依次实例化父类对象和子类对象(父类--非静态代码块;父类--构造函数;子类--非静态代码块;子类--构造函数;)

推测:若将EXA的静态块和静态属性的初始化换位置,执行结果应该为:

父类--静态代码块

父类--非静态代码块
父类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
子类--静态代码块
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数
父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数

public class EXA {          static {          System.out.println("父类--静态代码块");      }     private static EXA a = new EXA();      public EXA() {          System.out.println("父类--构造函数");      }        {          System.out.println("父类--非静态代码块");      }        public static void main(String[] args) {        new EXC();        new EXC();    }}class EXC extends EXA {      private static EXC b = new EXC();      static {          System.out.println("子类--静态代码块");      }      {          System.out.println("子类--非静态代码块");      }        public EXC() {          System.out.println("子类--构造函数");      }}

运行发现,结果证实这样。

posted @
2017-09-27 10:41 阅读(
...) 评论(
...)

转载地址:http://chqci.baihongyu.com/

你可能感兴趣的文章
Yotta企业云盘更好地为教育行业服务
查看>>
Yotta企业云盘怎么帮助到能源化工行业
查看>>
企业云盘如何助力商业新发展
查看>>
医疗行业运用企业云盘可以带来什么样的提升
查看>>
媒体广告业如何将内容资产进行高效地综合管理与利用
查看>>
能源化工要怎么管控核心数据
查看>>
媒体广告业如何运用云盘提升效率
查看>>
企业如何运用企业云盘进行数字化转型-实现新发展
查看>>
司法如何运用电子智能化加快现代化建设
查看>>
iSecret 1.1 正在审核中
查看>>
IOS开发的开源库
查看>>
IOS开发的开源库
查看>>
Jenkins - sonarqube 代码审查
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成(一)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 单机部署(二)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
查看>>
Golang struct 指针引用用法(声明入门篇)
查看>>
Linux 粘滞位 suid sgid
查看>>
C#控件集DotNetBar安装及破解
查看>>
Winform皮肤控件IrisSkin4.dll使用
查看>>