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

CKR*_*666 81 java inheritance constructor static-block

我有两个班级父母和孩子

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();    
    }
}
Run Code Online (Sandbox Code Playgroud)

上面代码的输出将是

Parent static block
Child static block
Parent initialization  block
Parent Constructor
Child initialization block
Child Constructor
Run Code Online (Sandbox Code Playgroud)

为什么Java按该顺序执行代码?确定执行顺序的规则是什么?

Pet*_*sik 54

有几个规则在起作用

  • 静态块始终在创建对象之前运行,因此您可以看到来自父级和子级静态块的打印消息
  • 现在,当您调用子类(子)的构造函数时,此构造函数super();在执行它自己的构造函数之前隐式调用.初始化块甚至在构造函数调用之前就会发挥作用,因此这就是它首先被调用的原因.所以现在创建了父级,程序可以继续创建将经历相同过程的子类.

说明:

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


Ben*_*ero 45

我在视觉上学习,所以这里是订单的直观表示,作为一个SSCCE:

public class Example {

  static {
    step(1);
  }

  public static int step_2 = step(2);
  public int step_6 = step(6);

  public Example() {
    step(8);
  }

  {
    step(7);
  }

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

public class ExampleSubclass extends Example {

  {
    step(9);
  }

  public static int step_3 = step(3);
  public int step_10 = step(10);

  static {
    step(4);
  }

  public ExampleSubclass() {
    step(11);
  }

  public static void main(String[] args) {
    step(5);
    new ExampleSubclass();
    step(12);
  }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7
Step 8
Step 9
Step 10
Step 11
Step 12
Run Code Online (Sandbox Code Playgroud)

请记住,部件的顺序很static重要; 回头看的秩序之间的区别Examplestatic东西,ExampleSubclass的.

另请注意,实例初始化块始终在构造函数之前执行,无论顺序如何.但是,顺序在初始化块和字段初始化程序之间确实很重要.

  • 请附上任何反对票的理由,以便我知道将来如何写出更好的答案:) (3认同)

Raú*_*aúl 10

首先运行子类(注释extend子句)以查看简单流.

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

编辑:

  1. 执行以SIC方式执行 - 静态,(非静态)初始化程序和构造函数.
  2. (非静态)初始化程序被复制到每个构造函数中 - 在TOP!(因此第3/4/5/6行)
  3. 在初始化类之前,必须初始化其直接超类 - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4(因此首先出现父静态块) .


小智 7

  • 静态初始化块在类加载时执行。
  • 在类层次结构中,静态初始化块的执行顺序将从顶级类开始。
  • 在一个类中,执行静态块的顺序是从上到下。
  • 无论该类中的静态块存在于何处,上述规则均适用。

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

  • 实例初始化块将在调用super()之后执行;在构造函数中。
    • 总是super(); 是默认构造函数中的第一条语句。

在创建子对象时,在代码中:

  • Child类的默认构造函数得到执行。
  • 它将调用super();。构造函数。
  • 然后执行超类构造函数。
  • Parent类将执行其super(); 呼叫。
  • 之后,执行Parent类中的实例初始化块。(从上到下)。
  • 然后执行构造函数中的代码(如果有)。
  • 然后它将返回Child类并执行Child类实例的init块。
  • 最后,子构造函数中的代码得到执行(如果存在)。


小智 5

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

所以先执行静态块.

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

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

然后执行构造函数