2013-10-24 51 views
62

我有两个类亲子使用继承时,静态块和初始化块以什么顺序执行?

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中的顺序执行的代码?决定执行顺序的规则是什么?

+4

非常有趣的问题。谢谢 –

+0

随着更新版本的Java(1.7及更高版本),JVM将抛出一个运行时异常,因为即使您有一个静态块,它在该类中也找不到主要方法。 – lft93ryt

回答

37

有在玩一些规则

  • 静态块的对象之前,总是跑创建,所以这就是为什么你的父母和孩子的静态块现在
  • 都可以看到打印的信息,当你调用子类(child)的构造函数,那么这个构造函数在执行它自己的构造函数之前隐式调用​​。即使在构造函数调用之前,初始化块也会发挥作用,所以这就是为什么它首先被调用。所以现在你的父母被创建并且程序可以继续创建将经历相同过程的子类。

说明:首先执行

  1. 父静块,因为它是加载的第一和加载类时的静止象素块被调用。
+1

为什么父级的静态块首先被执行?我正在运行子级 – CKR666

+2

@ CKR666因为它是**加载的第一个**,并且在加载类时调用静态块。 – Maroun

+0

但我正在运行子类 – CKR666

4

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

所以静态块首先执行。

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

so next创建类的实例时执行的初始化块。

然后构造执行

+0

为什么父类的静态块首先被执行....?我是先加载子类吗? – CKR666

+1

@ CKR666 - 请参阅下面的更新! –

7

首先 - 运行子类只(注释的扩展条款)看简单的流量。

秒 - 去Static block vs. initializer block in Java? &阅读那里接受的答案。

编辑:

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

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

2

用一步一步的debuger查看对象构造过程将会非常有帮助,其中有一个视图,您可以在其中查看对象如何在各个阶段中进行磨合。我发现这对于从更高的角度清除角度非常有用。 Eclipse可以帮助你通过它的调试器进入功能。

26

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

public class Example { 

    static { 
    step(1); 
    } 

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

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

此打印:

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

请记住,static部分事项的顺序;回顾一下Examplestatic东西和ExampleSubclass的差别。

+1

正在通过您的SSCCE评论。有趣! – lft93ryt

+0

@ lft93ryt我希望它有帮助:D –

+0

非常有用,在学习顺序,谢谢! –

0

控制流是 -

静块 - >初始化块 - >并最终构造。

静态块 - >这个静态块将得到执行只有一次当控制前来类(JVM加载这个类)

初始化模块 - >这个初始化块将得到执行,每当创建的类的新对象(它会从构造函数,然后下面的构造函数的第二条语句执行报表─记得构造的第一句会超()/()这个)

构造函数 - >这无线只要有新的对象被创建,就会被获取。

2

只是想分享我的发现。 我在另一个线程的其中一个答案中读到静态块在静态域不正确之前首先被执行。它取决于哪个先出现,静态字段或静态块。看看下面的代码。它会试图把事情放在角度。

  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 
2

这是我发现的,同时准备进行认证。

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

然后,它会执行初始化块/实例变量initialisation.If多个初始化块/变量初始化都是存在的,它会在执行它它出现的顺序,

之后它会查看构造函数。