静态块vs初始化块与继承中的构造函数

 天呀你呀_778 发布于 2023-01-29 20:02

我找到这个例子,我想了解它背后的逻辑?构造函数和静态块以及初始化程序块如何在继承中工作?在哪个阶段被称为?

public class Parent {

    static {
        System.out.println("i am Parent 3");
    }

    {
        System.out.println("i am parent 2");
    }

    public Parent() {
        System.out.println("i am parent 1");
    }

}

public class Son extends Parent {

    static {System.out.println("i am son 3");}
    {System.out.println("i am son 2");}

    public Son() {
        System.out.println("i am son 1");
    }

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

输出是:

i am Parent 3
i am son 3
i am parent 2
i am parent 1
i am son 2
i am son 1

Pshemo.. 11

你需要知道这一点

    构造函数中的第一条指令是调用其父类的构造函数,super(params)或者是否要使用默认构造函数super().在默认构造函数的情况下,您不必显式编写它.

    初始化程序块中的代码在super(...)调用后立即移动到每个构造函数

    初始化类时执行静态块,这是在JVM完全加载(使用其父类)之后完成的.

所以类被编译成类似于此的类.

public class Parent {
    static {
        System.out.println("Parent static block");
    }

    public Parent() {
        super();
        {
            System.out.println("Parent initializer block");
        }
        System.out.println("Parent constructor");
    }

}

public class Son extends Parent {

    static {
        System.out.println("Son static block");
    }

    public Son() {
        super();
        {
            System.out.println("Son initializer block");
        }
        System.out.println("Son constructor");
    }

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

为了能够mainSon类JVM 执行方法,需要加载此类的代码(以及它扩展的类).在类完全加载后,JVM 初始化其静态内容,这涉及执行静态块(是的,一个类中可能有多个静态块).要完全加载Son类JVM需要知道有关其父类的详细信息,以便它完全加载Parent类,Son这意味着它还将在Son类中的静态块之前执行其静态块.

所以输出看起来像:

Parent static block

Son static block

现在在main方法中,您正在调用Son类构造函数new Son(),代码看起来像这样

super();
{
    System.out.println("Son initializer block");
}
System.out.println("Son constructor");

由于它super()引用了Parent类构造函数,因此

super();// this will invoke Object constructor since Parent 
        // doesn't extend anything (which means it extends Object class)
{
    System.out.println("Parent initializer block");
}
System.out.println("Parent constructor");

结果你会看到

Parent initializer block

Parent constructor

这个句柄随后Parent#constructor()执行,super()你将看到Son构造函数的代码,之后super()将生成

Son initializer block

Son constructor


要在使用Son构造函数甚至main方法之前看到类将被加载,你可以在使用Son构造函数之前打印一些东西

System.out.println("ABC                      // before new Son()");
new Son();

这将导致

Parent static block
Son static block
ABC                      // before new Son()
Parent initializer block
Parent constructor
Son initializer block
Son constructor


JB Nizet.. 9

当类由JVM加载并初始化时,会调用一次静态块.在构造类的实例时执行实例初始化程序,就像构造函数一样.

静态和实例初始值设定项在Java语言规范中描述

2 个回答
  • 你需要知道这一点

      构造函数中的第一条指令是调用其父类的构造函数,super(params)或者是否要使用默认构造函数super().在默认构造函数的情况下,您不必显式编写它.

      初始化程序块中的代码在super(...)调用后立即移动到每个构造函数

      初始化类时执行静态块,这是在JVM完全加载(使用其父类)之后完成的.

    所以类被编译成类似于此的类.

    public class Parent {
        static {
            System.out.println("Parent static block");
        }
    
        public Parent() {
            super();
            {
                System.out.println("Parent initializer block");
            }
            System.out.println("Parent constructor");
        }
    
    }
    
    public class Son extends Parent {
    
        static {
            System.out.println("Son static block");
        }
    
        public Son() {
            super();
            {
                System.out.println("Son initializer block");
            }
            System.out.println("Son constructor");
        }
    
        public static void main(String[] args) {
            new Son();
        }
    }
    

    为了能够mainSon类JVM 执行方法,需要加载此类的代码(以及它扩展的类).在类完全加载后,JVM 初始化其静态内容,这涉及执行静态块(是的,一个类中可能有多个静态块).要完全加载Son类JVM需要知道有关其父类的详细信息,以便它完全加载Parent类,Son这意味着它还将在Son类中的静态块之前执行其静态块.

    所以输出看起来像:

    Parent static block

    Son static block

    现在在main方法中,您正在调用Son类构造函数new Son(),代码看起来像这样

    super();
    {
        System.out.println("Son initializer block");
    }
    System.out.println("Son constructor");
    

    由于它super()引用了Parent类构造函数,因此

    super();// this will invoke Object constructor since Parent 
            // doesn't extend anything (which means it extends Object class)
    {
        System.out.println("Parent initializer block");
    }
    System.out.println("Parent constructor");
    

    结果你会看到

    Parent initializer block

    Parent constructor

    这个句柄随后Parent#constructor()执行,super()你将看到Son构造函数的代码,之后super()将生成

    Son initializer block

    Son constructor


    要在使用Son构造函数甚至main方法之前看到类将被加载,你可以在使用Son构造函数之前打印一些东西

    System.out.println("ABC                      // before new Son()");
    new Son();
    

    这将导致

    Parent static block
    Son static block
    ABC                      // before new Son()
    Parent initializer block
    Parent constructor
    Son initializer block
    Son constructor
    

    2023-01-29 20:06 回答
  • 当类由JVM加载并初始化时,会调用一次静态块.在构造类的实例时执行实例初始化程序,就像构造函数一样.

    静态和实例初始值设定项在Java语言规范中描述

    2023-01-29 20:06 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有