在官方的Java指南“Programming with assertions”中指出(页面的最后一段)
很少有程序员意识到类的构造函数和方法可以在其初始化之前运行。当这种情况发生时,类的不变量很可能还没有建立,这可能会导致严重而微妙的错误。
这是什么意思?什么时候会发生这种情况?这是我在日常使用Java时必须关心的事情吗?
发布于 2011-11-18 02:10:04
基本上,他们谈到了以下情况:
public class Foo {
public static Foo INSTANCE = new Foo(); // Prints null
public static String s = "bar";
public Foo() {
System.out.println(s);
}
}
正如你所看到的,在这种情况下,构造器在静态字段s
的初始化器之前运行,即在类的完全初始化之前。这只是一个简单的例子,但当涉及到多个类时,它可能会变得更复杂。
这在你的日常工作中并不常见,但你需要意识到这种可能性,并在编写代码时避免它。
发布于 2011-11-18 02:10:50
例如,考虑构造函数中的虚方法分派。
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
基类处于某种状态。
发布于 2011-11-18 02:11:08
我认为它们指的是逻辑初始化。例如,您的类A具有在使用任何业务方法之前必须调用的方法init()
。但是其他使用这个类的程序员还没有读过手册,也没有写过new A().foo()
。在这种情况下,foo()
可能无法正常工作。在这种情况下,断言可能是有用的。您可以在开始时检查init()
未被调用并抛出断言。
构造函数也是如此。当有人扩展你的类A时,可能会发生这种情况:
class B extends A {
B() {
foo(); // init() must be called before foo!
}
}
https://stackoverflow.com/questions/8172074
复制相似问题