究竟是在什么时候调用静态块或方法

时间:2013-07-04 12:54:14

标签: java

下面是一个程序,其中有两个静态块,我认为应该在第一次通知时调用,但按顺序从上到下但不会发生

public class StaticTest {  
    public static void main(String[] args) {  
        A a1 = new A();  
        A a2 = new A();  
        B b1 = new B();  
    }
}  

class A {  
    static {  
        System.out.println("Static block of Class A");  
    }  
    {  
        System.out.println("Non-Static block of a instance of Class A");  
    }  
    public A() {  
        System.out.println("Constructing object of type A");  
    }  
}  
class B {  
    static {  
        System.out.println("Static block of Class B");  
    }
    {  
        System.out.println("Non-Static block of a instance of Class B");  
    }
    public B() {  
        System.out.println("Constructing object of type A");  
    }  
}   

5 个答案:

答案 0 :(得分:3)

正好在什么时候调用静态块或方法” - 对于这样的问题,Java Language Specification可以为您解答。

Static initializer

  

在类中声明的类中声明的静态初始化程序   初始化。与课程的任何字段初始化程序一起使用   变量,静态初始化器可用于初始化   类的类变量。

通过运行代码,您可以轻松找出最先运行的代码。

答案 1 :(得分:2)

class B中的静态块在实际需要B之前不会执行。这只是主方法的第3个语句中的情况。实际上,如果用

替换该行
if (2*2 == 5) new B();

您会注意到B的静态块永远不会被执行,因为B甚至不会被加载。

要跟踪类加载,请使用java命令的-verbose:class选项。

答案 2 :(得分:1)

这是测试的输出

Static block of Class A
Non-Static block of a instance of Class A
Constructing object of type A
Non-Static block of a instance of Class A
Constructing object of type A
Static block of Class B
Non-Static block of a instance of Class B
Constructing object of type A

我很惊讶你为什么Static block of Class A只打印一次。这是因为静态块在类加载时只运行一次。致电new A()后 JVM加载了A.class,当您再次调用new A()时,无需再次加载

答案 3 :(得分:1)

初始化各个类时执行静态块。

类初始化的顺序由所涉及的类之间的静态和动态依赖关系的组合决定;见When does static class initialization happen?

然而,JLS实际上提供了一组约束(在此之前发生),通常有许多解决方案。这是一个例子,其中两个“解决方案”是可能的。

  1. A表达式构建new A()

  2. 之前,类A已初始化
  3. B表达式构建new B()

  4. 之前,类B已初始化

    如您所见,在A之前初始化类BB之前Asuper(...)

    在这种情况下,未指定实际的初始化顺序,并且可能依赖于JVM和/或字节码编译器......并且不应该依赖它。

    还可以构造一种场景,其中依赖关系中存在循环,这导致不存在满足约束的顺序。在这种情况下,顺序也是不确定的,并且其中一个类可以观察未初始化状态中的另一个类。 (编译器或运行时都没有将此标记为错误!)这在JLS部分8.3.2.3中有所描述。

    幸运的是,这种情况非常不寻常。


    实例块和静态方法要简单得多:

    • 每次创建实例时,都会按程序顺序执行类的实例块。它们在构造函数的super()“call”和该构造函数的下一行之间按顺序执行。 (当构造函数是默认构造函数和/或隐式{{1}}调用时,同样适用。)

    • 静态方法在显式调用时执行。

答案 4 :(得分:0)

以下是程序的输出

Static block of Class A
Non-Static block of a instance of Class A
Constructing object of type A
Non-Static block of a instance of Class A
Constructing object of type A
Static block of Class B
Non-Static block of a instance of Class B
Constructing object of type A

静态块仅在创建第一次类对象时调用