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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21504726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:02:56  来源:igfitidea点击:

static block vs initializer block vs constructor in inheritance

javainheritanceconstructorpolymorphismstatic-block

提问by oussama.elhadri

i find this example and i want to understand the logic behind it ? how constructors and static blocks and initializer blocks works in inheritance ? in which stage each one is called ?

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

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();
    }
}

the output is :

输出是:

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

采纳答案by JB Nizet

A static block is called once, when the class is loaded and initialized by the JVM. An instance initializer is executed when an instance of the class is constructed, just like a constructor.

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

Static and Instance initializers are described in the Java Language Specification

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

回答by Vivek Vermani

Static block gets executed when the class is loaded into JVM whereas constructor block gets executed when an instance is created.

静态块在类加载到 JVM 时执行,而构造函数块在创建实例时执行。

A static initializer is the equivalent of a constructor in the static context. You will certainly see that more often than an instance initializer.

静态初始化器相当于静态上下文中的构造函数。您肯定会比实例初始化程序更频繁地看到它。

回答by Girish

Static block called when your class is loaded and your class is first loaded by classloader in jvm so first they get executed

静态块在您的类加载时调用,并且您的类首先由 jvm 中的类加载器加载,因此它们首先被执行

then you create object so your parent init block is called then your parent constructor due to constructor chaining in java then derived class init block then derived class constructor

然后你创建对象所以你的父init块被调用然后你的父构造函数由于java中的构造函数链接然后派生类init块然后派生类构造函数

回答by Pshemo

You need to know that

你需要知道

  1. first instruction in constructor is invoking constructor of its parent class super(params)or if you want to use default constructor super(). In case of default constructor you don't have to write it explicitly.
  2. code in initializer block is moved to every constructor right after super(...)call
  3. static block is executed when class is initialized which is done after it is fully loaded (with its parent classes) by JVM.
  1. 构造函数中的第一条指令是调用其父类的构造函数,super(params)或者如果您想使用默认构造函数super()。在默认构造函数的情况下,您不必显式编写它。
  2. 初始化块中的代码在super(...)调用后立即移动到每个构造函数
  3. 静态块在类初始化时执行,这是在 JVM 完全加载(及其父类)后完成的。

So classes are compiled into classes similar to this.

所以类被编译成与此类似的类。

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();
    }
}

To be able to execute mainmethod from Sonclass JVM needs to loadcode of this class (and classes it extends). After class is fully loaded JVM initializeits static content which involves executing static blocks (yes, there can be more then one static blocks in one class). To fully load Sonclass JVM needs to know details about its parent class so it will fully load Parentclass before Sonwhich means it will also execute its static blocks before static blocks in Sonclass.

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

So output will look like:

所以输出看起来像:

  • Parent static block
  • Son static block
  • Parent static block
  • Son static block

Now in mainmethod you are invoking Sonclass constructor via new Son()which code looks like

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

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

Since its super()refer to Parentclass constructor, which is

由于它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");

as result you will see

结果你会看到

  • Parent initializer block
  • Parent constructor
  • Parent initializer block
  • Parent constructor

This handles Parent#constructor()executed with super()so next you will see code from Son constructor after super()which will generate

这个句柄Parent#constructor()执行,super()所以接下来你会看到来自 Son 构造函数的代码,之后super()将生成

  • Son initializer block
  • Son constructor
  • Son initializer block
  • Son constructor


To see that classes will be loaded even before you use Sonconstructor or even mainmethod you can just print something before using Sonconstructor like

要查看甚至在使用Son构造函数甚至main方法之前加载类,您可以在使用Son构造函数之前打印一些内容,例如

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

which will result in

这将导致

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