Java 使用继承时,静态块和初始化块以什么顺序执行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19561332/
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-12 18:20:40  来源:igfitidea点击:

In what order do static blocks and initialization blocks execute when using inheritance?

javainheritanceconstructorstatic-block

提问by CKR666

I have two classes Parent and Child

我有两个班级 Parent 和 Child

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

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

    public Child() {
        System.out.println("Child Constructor");
    }    
    public static void main(String[] args) {
        new Child();    
    }
}

The output of the above code will be

上述代码的输出将是

Parent static block
Child static block
Parent initialization  block
Parent Constructor
Child initialization block
Child Constructor

Why does Java execute the code in that order? What are the rules that determine the execution order?

为什么Java按这个顺序执行代码?决定执行顺序的规则是什么?

回答by Petr Mensik

There are several rules in play

有几个规则在玩

  • static blocks are always run before the object is created, so that's why you see print messages from both parents and child static blocks
  • now, when you are calling constructor of the subclass (child), then this constructor implicitly calls super();before executing it's own constructor. Initialization block comes into play even before the constructor call, so that's why it is called first. So now your parent is created and the program can continue creating child class which will undergo the same process.
  • 静态块始终在创建对象之前运行,因此您会看到来自父静态块和子静态块的打印消息
  • 现在,当您调用子类(子类)的构造函数时,此构造函数super();在执行它自己的构造函数之前会隐式调用。初始化块甚至在构造函数调用之前就开始发挥作用,所以这就是首先调用它的原因。因此,现在您的父类已创建,程序可以继续创建将经历相同过程的子类。

Explanations:

  1. Static block of parent is executed first because it is loaded firstand static blocks are called when the class is loaded.

说明:

  1. 首先执行父的静态块,因为它首先加载,并且在加载类时调用静态块。

回答by rohan kamat

Static block in java is executed before main method. If we declare a Static block in java class it is executed when class loads. This is initialize with the static variables. It is mostly used in JDBC. Static block in java is executed every time when a class loads. This is also known as Static initialization block. Static block in java initializes when class load into memory , it means when JVM read the byte code. Initialization can be anything; it can be variable initialization or anything else which should be shared by all objects of that class. Static block is a normal block of code enclosed in braces { } and is preceded by static keyword.

java中的静态块在main方法之前执行。如果我们在 java 类中声明一个静态块,它会在类加载时执行。这是用静态变量初始化的。它主要用于JDBC。每次加载类时都会执行java中的静态块。这也称为静态初始化块。java中的静态块在类加载到内存时初始化,这意味着JVM读取字节码时。初始化可以是任何东西;它可以是变量初始化或其他任何应该由该类的所有对象共享的内容。静态块是用大括号 {} 括起来的普通代码块,并以 static 关键字开头。

so static block executed first.

所以首先执行静态块。

Instance Initialization Blocks: Runs every time when the instance of the class is created.

实例初始化块:每次创建类的实例时运行。

so next Initialization block executed when instance of the class is created.

所以在创建类的实例时执行下一个初始化块。

then Constructor executed

然后构造函数执行

回答by Raúl

First - run child class only (comment the extend clause) to see the simple flow.

首先 - 仅运行子类(注释扩展子句)以查看简单流程。

second - go to Static block vs. initializer block in Java?& read the accepted answer over there.

第二 - 转到Java 中的静态块与初始化块?并阅读那里接受的答案。

Edit:

编辑:

  1. Execution happens in SIC way - Static, (non static) Initializer & Constructor.
  2. (Non static) Initializer are copied into every constructor - At the TOP! (hence lines 3/4/5/6)
  3. Before a class is initialized, its direct superclass must be initialized - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4(hence parent static block appears first).
  1. 执行以 SIC 方式发生 - 静态,(非静态)初始化器和构造器。
  2. (非静态)初始化程序被复制到每个构造函数中 - 在顶部!(因此第 3/4/5/6 行)
  3. 在初始化类之前,必须初始化其直接超类 - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4(因此父静态块首先出现) .

回答by Sunil Kumar Jha

Static block gets executed when a class is loaded into JVM. While init block gets copied into the Constructor whose object will be created and runs before creation of object.

将类加载到 JVM 时,会执行静态块。而 init 块被复制到构造函数中,其对象将在创建对象之前被创建和运行。

回答by Mihai Savin

It would be very helpful to ckeck out the object construction process with a step by step debuger, having a view in which you can see how your object is goning through the phases. I found this very useful for clearing the perspective from a higher point of view. Eclipse can help you with this with it's debugger step into function.

使用逐步调试器检查对象构建过程将非常有帮助,有一个视图,您可以在其中查看对象如何经历各个阶段。我发现这对于从更高的角度清除视角非常有用。Eclipse 可以通过调试器进入功能来帮助您解决这个问题。

回答by Ben Leggiero

I learn visually, so here's a visual representation of order, as a SSCCE:

我在视觉上学习,所以这里是顺序的视觉表示,作为SSCCE

public class Example {

    static {
        step(1);
    }

    public static int step_2 = step(2);
    public int step_8 = step(8);

    public Example(int unused) {
        super();
        step(10);
    }

    {
        step(9);
    }

    // Just for demonstration purposes:
    public static int step(int step) {
        System.out.println("Step " + step);
        return step;
    }
}
public class ExampleSubclass extends Example {

    {
        step(11);
    }

    public static int step_3 = step(3);
    public int step_12 = step(12);

    static {
        step(4);
    }

    public ExampleSubclass(int unused) {
        super(step(7));
        step(13);
    }

    public static void main(String[] args) {
        step(5);
        new ExampleSubclass(step(6));
        step(14);
    }
}

This prints:

这打印:

Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7
Step 8
Step 9
Step 10
Step 11
Step 12
Step 13
Step 14

Keep in mind that the order of the staticparts matters; look back at the difference between the order of Example's staticstuff and ExampleSubclass's.

请记住,static零件的顺序很重要;回顾一下Example's 的static东西和ExampleSubclass's的顺序的区别。

Also note that the instance initialization block is always executed immediately after the super()call in the constructor (even if that call is implied/omitted), no matter the order. However, order does matter between an initialization block and a field initializer.

另请注意,super()无论顺序如何,实例初始化块始终在构造函数中的调用之后立即执行(即使该调用是隐含/省略的)。但是,初始化块和字段初始化程序之间的顺序确实很重要。

回答by Prakash VL

control flow is-

控制流是-

static block -> Initialization block -> and finally Constructor.

静态块 -> 初始化块 -> 最后是构造函数。

static block -> This static block will be get executed only oncewhen the control come to the class.(JVM Load this class)

静态块 ->当控件到达类时,这个静态块只会被执行一次。(JVM 加载这个类)

Initialization block -> This Initialization block will be get executed whenever a new object Created for the Class (It will be executed from second statement of the Constructor then following constructor statements- remember First statement of the Constructor will be Super()/this())

初始化块 -> 每当为类创建新对象时,都会执行此初始化块(它将从构造函数的第二条语句开始执行,然后是构造函数语句-记住构造函数的第一条语句将是 Super()/this() )

Constructor -> This will be get whenever a new object is created.

构造函数 -> 这将在创建新对象时获取。

回答by pragun

Just wanted to share my findings. I read in one of the answers on another thread that static blocks are executed first before static fields which is not correct. It depends on which comes first, static field or static block. Have a look at below code. It will try to put things in perspective.

只是想分享我的发现。我在另一个线程上的一个答案中读到静态块在静态字段之前首先执行,这是不正确的。这取决于哪个先出现,静态字段或静态块。看看下面的代码。它将尝试正确看待事物。

  1. JVM looks for a class which has public static void main(String args[]) so that it can load that class.
  2. It then initialises static fields of this class(if they come before static blocks). These fields can call static methods of this class or another. If they call static method of this class then that method gets served. If they call static method of another class, then static fields or blocks of that class(depending on which comes first) gets initialised first, then this method call is served.
  3. Then, it moves to static blocks.
  4. It comes back to main method.

    class TestLab {
    static int method(String a) {
        System.out.println("in static method of TestLab" + " Coming from " + a);
        System.out.println("b is " + b);
        return 6;
    }
    
    static int a = method("Line 11");
    static int b = 7;
    
    TestLab() {
        System.out.println("Inside test lab constructor");
    }
    
    static {
        System.out.println("In static block of TestLab");
    }
    
    }
    
    public class Test1 {
    public static void main(String[] args) {
        System.out.println("inside main method of Test 1");
        int a = TestLab.method("Line 26");
    }
    
    // static Test ref=new Test();
    Test1() {
        System.out.println("Default Constructor of Test1");
    }
    
    {
        System.out.println("In instance block of Test1");
    }
    static int d = TestLab.method("Line 37");
    static int e = methodOfTest1();
    static {
        System.out.println("In Static Block of Test1");
    }
    
    static int methodOfTest1() {
        System.out.println("inside static method:mehtodOfTest1()");
        return 3;
    }
    }
    
  1. JVM 查找具有 public static void main(String args[]) 的类,以便它可以加载该类。
  2. 然后初始化此类的静态字段(如果它们位于静态块之前)。这些字段可以调用此类或其他类的静态方法。如果他们调用此类的静态方法,则该方法将被提供。如果他们调用另一个类的静态方法,则该类的静态字段或块(取决于哪个先出现)首先初始化,然后提供此方法调用。
  3. 然后,它移动到静态块。
  4. 它回到 main 方法。

    class TestLab {
    static int method(String a) {
        System.out.println("in static method of TestLab" + " Coming from " + a);
        System.out.println("b is " + b);
        return 6;
    }
    
    static int a = method("Line 11");
    static int b = 7;
    
    TestLab() {
        System.out.println("Inside test lab constructor");
    }
    
    static {
        System.out.println("In static block of TestLab");
    }
    
    }
    
    public class Test1 {
    public static void main(String[] args) {
        System.out.println("inside main method of Test 1");
        int a = TestLab.method("Line 26");
    }
    
    // static Test ref=new Test();
    Test1() {
        System.out.println("Default Constructor of Test1");
    }
    
    {
        System.out.println("In instance block of Test1");
    }
    static int d = TestLab.method("Line 37");
    static int e = methodOfTest1();
    static {
        System.out.println("In Static Block of Test1");
    }
    
    static int methodOfTest1() {
        System.out.println("inside static method:mehtodOfTest1()");
        return 3;
    }
    }
    

Here is the output:

这是输出:

in static method of TestLab Coming from Line 11
b is 0
In static block of TestLab
in static method of TestLab Coming from Line 37
b is 7
inside static method:mehtodOfTest1()
In Static Block of Test1
inside main method of Test 1
in static method of TestLab Coming from Line 26
b is 7

回答by PRAVEEN PS

Here is what I found while preparing for a certification.

这是我在准备认证时发现的。

While we run a class, first static blocks/ static variable initialisation happens. If multiple static blocks are there, it will execute it in the order in which it appears,

当我们运行一个类时,首先会发生静态块/静态变量初始化。如果有多个静态块,它会按照它出现的顺序执行,

Then it will execute init blocks/ instance variable initialisation.If multiple init blocks/ variable initialisation are there, it will execute it in the order in which it appears,

然后它会执行init块/实例变量初始化。如果有多个init块/变量初始化,它会按照出现的顺序执行,

Afterwards it will look into the constructor.

之后它将查看构造函数。

回答by Sayanthan Mahendran

  • Static init blocks are executed at the time of class loading.
  • In the class hierarchy the order for execution of static init blocks will start from top level class.
  • In a class the order for the execution of static block is from top to bottom.
  • Above rule apply regardless of where the static block is present within the class.
  • 静态初始化块在类加载时执行。
  • 在类层次结构中,静态初始化块的执行顺序将从顶级类开始。
  • 在一个类中,静态块的执行顺序是从上到下。
  • 无论静态块存在于类中的何处,上述规则都适用。

(In your code the parent static blocks will be executed first and then the child class static blocks.)

(在您的代码中,将首先执行父静态块,然后执行子类静态块。)

  • Instance init blocks will be executed after the call to the super(); in the constructor.
    • Always super(); is the very first statement in a default constructor.
  • 实例初始化块将在调用 super() 后执行;在构造函数中。
    • 总是超级(); 是默认构造函数中的第一条语句。

In your code when you create a Child object:

在您创建 Child 对象时的代码中:

  • The default constructor of the Child class get executed.
  • It will call to the super(); constructor.
  • Then the super class constructor is executed.
  • The Parent class will execute its super(); call.
  • After that the instance init blocks in the Parent class are executed.(From top to bottom).
  • Then the code within the constructor is executed (if any).
  • Then it will return to the Child class and execute the Child class instance init blocks.
  • Finally the code in the child constructor get executed (If exists).
  • Child 类的默认构造函数被执行。
  • 它将调用 super(); 构造函数。
  • 然后执行超类构造函数。
  • Parent 类将执行它的 super(); 称呼。
  • 之后执行 Parent 类中的实例 init 块。(从上到下)。
  • 然后执行构造函数中的代码(如果有的话)。
  • 然后它将返回到 Child 类并执行 Child 类实例 init 块。
  • 最后执行子构造函数中的代码(如果存在)。