在官方Java指南“Programming with assertions”中说明了这一点 (页面上的最后一段)
很少有程序员意识到类的构造函数和方法可以在初始化之前运行。当发生这种情况时,很可能该类的不变量尚未建立,这可能会导致严重和微妙的错误。
这是什么意思?这是什么时候发生的?我在日常使用Java时是否需要关注它?
答案 0 :(得分:29)
基本上,他们谈论以下情况:
public class Foo {
public static Foo INSTANCE = new Foo(); // Prints null
public static String s = "bar";
public Foo() {
System.out.println(s);
}
}
正如您所看到的,在这种情况下,构造函数在静态字段s
的初始化程序之前运行,i。即在完全初始化类之前。这只是一个简单的例子,但是当涉及多个类时它会变得更加复杂。
这不是你在日常工作中经常看到的东西,但你需要意识到这种可能性,并在编写代码时避免使用它。
答案 1 :(得分:5)
例如,考虑构造函数中的虚方法调度。
class Foo {
Foo() {
int a = bar();
b = 7;
}
private int b;
protected int baz() { assert b == 7; return b; } ;
protected abstract int bar();
}
如果一个子类碰巧在baz
的实现中调用了bar
,那么他们就会遇到这个断言。该对象尚未完成构造,因此Foo
基类处于某种状态。
答案 2 :(得分:0)
我认为它们意味着逻辑初始化。例如,您的类A具有方法init()
,必须在使用任何业务方法之前调用它。但是使用这个类的其他程序员还没有阅读手册并写了new A().foo()
。在这种情况下,foo()
可能无法正常工作。在这种情况下,断言可能是有用的。您可以在开头检查init()
未被调用并抛出断言。
构造函数也是如此。当有人扩展你的A类时可能会发生这种情况:
class B extends A {
B() {
foo(); // init() must be called before foo!
}
}