“很少有程序员知道一个事实,即类的构造函数和方法可以在初始化之前运行”

2022-09-02 20:31:19

在官方Java指南“使用断言编程”中指出(页面上的最后一段)

很少有程序员知道类的构造函数和方法可以在其初始化之前运行。当这种情况发生时,很可能类的不变量尚未建立,这可能会导致严重而微妙的错误。

这是什么意思?这种情况何时发生?这是我在日常使用Java时必须关心的事情吗?


答案 1

基本上,他们谈论以下情况:

public class Foo {
    public static Foo INSTANCE = new Foo(); // Prints null

    public static String s = "bar";

    public Foo() {
        System.out.println(s);
    }
}

如您所见,在这种情况下,构造函数在静态字段的初始值设定项之前运行,即在类的完全初始化之前。这只是一个简单的示例,但是当涉及多个类时,它可能会变得更加复杂。s

这不是你在日常工作中经常能看到的东西,但你需要意识到这种可能性,并在编写代码时避免它。


答案 2

例如,考虑构造函数中的虚拟方法调度。

class Foo {
   Foo() {
      int a = bar();        
      b = 7;
   }

   private int b;

   protected int baz() { assert b == 7; return b; } ;

   protected abstract int bar();
}

如果一个子类碰巧从他们的实现内部调用,他们就会命中断言。对象尚未完成构造,因此基类处于某种状态。bazbarFoo