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

我有两个class级父母和孩子

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

上面的代码的输出将是

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

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

有几个规则在玩

  • 静态块总是在创build对象之前运行,所以这就是为什么您会看到来自父级和子静态块的打印消息
  • 现在,当你调用子类(child)的构造函数时,这个构造函数隐式调用super(); 在执行它自己的构造函数之前。 即使在构造函数调用之前,初始化块也会起作用,所以这就是为什么它被首先调用。 所以,现在你的父母被创build,程序可以继续创build子类,它将经历相同的过程。

说明:

  1. 父对象的静态块首先被执行,因为它被首先加载,而静态块在加载类时被调用。

我从视觉上学习,所以这里是一个可视化的秩序表示,作为一个SSCCE:

 public class Example { public static int step_1 = step(1); public int step_6 = step(6); static { step(2); } public Example() { step(7); } // Just for demonstration purposes: public static int step(int step) { System.out.println("Step " + step); return step; } } public class ExampleSubclass extends Example { public static int step_3 = step(3); public int step_8 = step(8); static { step(4); } public ExampleSubclass() { step(9); } public static void main(String[] args) { step(5); new ExampleSubclass(); } } 

这打印:

 Step 1 Step 2 Step 3 Step 4 Step 5 Step 6 Step 7 Step 8 Step 9 

首先只运行子类(注释扩展子句)来看简单的stream程。

第二个 – 去Java的静态块与初始化块? 并阅读那里接受的答案。

编辑:

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

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

所以静态块首先执行。

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

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

然后执行构造函数

用一步一步的debuger来清理对象构造过程是非常有帮助的,有一个你可以看到你的对象是如何在各个阶段中磨合的视图。 我发现这对于从更高的angular度来看清透视非常有用。 Eclipse可以通过它的debugging器来帮助你。

只是想分享我的发现。 我读了另一个线程的答案之一,静态块之前执行静态块是不正确的。 这取决于哪个先来,静态字段或静态块。 看看下面的代码。 它会试图把事情的angular度来看待。

  1. JVM寻找一个具有public static void main(String args [])的类,以便它可以加载该类。
  2. 然后它初始化这个类的静态字段(如果它们在静态块之前)。 这些字段可以调用这个类或另一个类的静态方法。 如果他们调用这个类的静态方法,那么该方法得到服务。 如果他们调用另一个类的静态方法,那么该类的静态字段或块(取决于哪个先来)被初始化,然后调用这个方法。
  3. 然后,它移动到静态块。
  4. 它回到主要方法。

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

这是输出:

 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 

这是我在准备authentication时发现的。

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

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

之后它会查看构造函数。

当一个类被加载到JVM中时,静态块被执行。 init块被复制到构造函数中,该构造函数的对象将被创build并在创build对象之前运行。

控制stream程是 –

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

静态块 – >当控件进入类时,这个静态块被执行一次 (JVM加载这个类)

初始化块 – >这个初始化块将被执行,每当一个新的对象为Class创build(它将从构造函数的第二个语句执行,然后在构造函数语句 – 记住构造函数的第一个语句将Super()/ this() )

构造函数 – >这将会得到每当一个新的对象被创build。