由基类导出的新类,它们之间构造器、静态块和非静态块的初始化顺序及原因

有这样一个问题:
例如下面这样的代码块,通过实例化导出类的构造器方法,最后结果是什么?

class Example{
    {
        System.out.println("super Example non-static");
    }
    public Example(){
        System.out.println("super Example constructor");
    }
    static {
        System.out.println("super B static");
    }

}
public class ConstructorExample extends Example{
    static {
        System.out.println("this static");
    }
    {
        System.out.println("this non-static");
    }
    public ConstructorExample(){
        System.out.println("this constructor");
    }

    public static void main(String[] args) {
        ConstructorExample example = new ConstructorExample();
    }

}

这段代码,对于子类跟其父类来说,都有构造器方法、静态块和非静态块,将程序运行之后,可得结果如下:
在这里插入图片描述

由此,结论:
首先,每个类的初始化顺序为静态变量、静态块、实例变量、实例块、构造器。
由此,对于某个基类导出的新类
1)先初始化父类的静态块、接下来是子类的静态块。
静态关键字表示只能被初始化一次,只占用一份内存。
2)对父类的非静态块和构造器依次进行初始化
3)初始化子类的非静态块,构造器
4)静态块与静态块之间、非静态块与非静态块之间的顺序则是按照先后顺序进行初始化(经检测无误,这不是写这篇博客的目的,未在代码中体现)
5)静态块只被初始化一次,而非静态块和构造器方法会随着 new 关键字被重新初始化一次,顺序如 2)、3)

如下:

class Example{
    {
        System.out.println("super Example non-static");
    }
    public Example(){
        System.out.println("super Example constructor");
    }
    static {
        System.out.println("super B static");
    }

}
public class ConstructorExample extends Example{
    static {
        System.out.println("this static");
    }
    {
        System.out.println("this non-static");
    }
    public ConstructorExample(){
        System.out.println("this constructor");
    }

    public static void main(String[] args) {
        new ConstructorExample();
        new ConstructorExample();
    }

}

在这里插入图片描述
其中静态块只被初始化一次,非静态块和构造器方法随着 new 关键字的出现被初始化两次。

原因:
子类的构造器中默认含有父类的构造器

 public ConstructorExample(){
        System.out.println("this constructor");
    }
//等价于
 public ConstructorExample(){
        super();
        System.out.println("this constructor");
    }

所以对子类初始化的时候会对父类进行初始化,如果不使用默认的构造器,调用子类构造器时,可以调用我们自己定义的构造器

class Example{
    {
        System.out.println("super Example non-static");
    }
    public Example(int a){
        System.out.println("super Example has a parameter");
    }
    public Example(){
        System.out.println("super Example constructor");
    }
    static {
        System.out.println();
    }
    static {
        System.out.println("super B static");
    }

}
public class ConstructorExample extends Example{
    static {
        System.out.println("this static");
    }
    {
        System.out.println("this non-static");
    }
    public ConstructorExample(){
        super(3);
        System.out.println("this constructor");
    }

    public static void main(String[] args) {
        new ConstructorExample();
    }

}

在这里插入图片描述
即使父类中有无参的构造器,而我们在子类的构造器中调用了有参的父类构造器,自然只能初始化父类有参的构造器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值