Java “;很少有程序员知道这样一个事实:类';s构造函数和方法可以在初始化之前运行”;
官方Java指南中指出 (本页最后一段) 很少有程序员知道,类的构造函数和方法可以在初始化之前运行。发生这种情况时,很可能类的不变量尚未建立,这可能会导致严重而微妙的错误Java “;很少有程序员知道这样一个事实:类';s构造函数和方法可以在初始化之前运行”;,java,initialization,Java,Initialization,官方Java指南中指出 (本页最后一段) 很少有程序员知道,类的构造函数和方法可以在初始化之前运行。发生这种情况时,很可能类的不变量尚未建立,这可能会导致严重而微妙的错误 这是什么意思?这是什么时候发生的?这是我在日常使用Java时必须关心的问题吗?基本上,他们讨论了以下情况: public class Foo { public static Foo INSTANCE = new Foo(); // Prints null public static String s = "b
这是什么意思?这是什么时候发生的?这是我在日常使用Java时必须关心的问题吗?基本上,他们讨论了以下情况:
public class Foo {
public static Foo INSTANCE = new Foo(); // Prints null
public static String s = "bar";
public Foo() {
System.out.println(s);
}
}
如您所见,在本例中,构造函数在静态字段s
的初始值设定项之前运行,即。E在类的完全初始化之前。这只是一个简单的示例,但当涉及多个类时,它可能会变得更复杂
这并不是你在日常工作中经常看到的事情,但是你需要意识到这种可能性,并在编写代码时避免它 > P>作为一个例子,考虑构造函数中的虚拟方法调度。
class Foo {
Foo() {
int a = bar();
b = 7;
}
private int b;
protected int baz() { assert b == 7; return b; } ;
protected abstract int bar();
}
如果一个子类碰巧从他们的
bar
实现中调用baz
,他们就会点击断言。对象尚未完成构造,因此Foo
基类处于某种状态。我认为它们是指逻辑初始化。例如,类A有一个方法init()
,必须在使用任何业务方法之前调用该方法。但其他使用该类的程序员并没有阅读手册,也并没有编写新的A().foo()。在这种情况下,foo()
可能无法正常工作。在这种情况下,断言可能很有用。您可以在开头检查未调用init()
,并抛出断言
构造函数也是如此。当有人扩展您的类A时,可能会发生这种情况:
class B extends A {
B() {
foo(); // init() must be called before foo!
}
}
什么是逻辑初始化(与仅初始化不同)?