我可以给它一个部分的解释。它指的是启用/禁用断言。断言由-ea
vm 参数启用。
一个重要的观点assert
是:
启用在其类完成初始化之前执行的断言语句。
假设-ea
没有给出并且您运行以下代码:
public class Q1 {
public static void main(String[] args) {
Bar b = new Bar();
}
}
class Bar {
static {
boolean enabled = false;
assert enabled = false; //line(a)
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
System.out.println("as");
Baz.testAsserts();
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
在上面的示例中,当b
被初始化时,Java 保证在line(a)
调用之前,断言被禁用(即 line(a) 根本不执行)。因为断言启用/禁用是类初始化的一部分,因此在您显示的相关语句中提到了它。
之所以提到顶级课程而不是其他所有课程,就是这个。更详细的行为在这里:
public class Q1 {
public static void main(String[] args) {
Baz.testAsserts();
// Will execute after Baz is initialized.
}
}
class Bar {
static {
Baz.testAsserts();
// Will execute before Baz is initialized!
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
即使-ea
没有使用标志,它仍然会抛出一个AssertionException
. 这是发生的事情:
- Q1.main 被称为
- Q1.main 调用 Baz.testAsserts。
- 因为 Baz 扩展了 Bar 并且 Bar 未初始化,所以根据 JLS 它尝试初始化 Bar
- 调用 Bar 的静态块。记住 assert 语句在其类完成初始化或调用 assert 之前启用(先发生)。在这种情况下,它
true
处于此阶段,因为Bar
仍未完全初始化
Bar
通话的静态Baz.testAsserts()
。断言仍处于启用状态(请记住,禁用断言与类初始化有关,并且 Bar 仍未完全初始化)。现在 Baz.testAsserts() throws AssertionException
。
上面是一个循环孔。JLS 只保证在执行任何assert
顶级类之前,它将禁用/启用(无论给出什么 vm 参数)它。但如果它不是顶级类,则行为取决于顶级类的初始化。要解释这一点,请参见:
class Bar {
static {
//Baz.testAsserts();
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
// Will execute before Baz is initialized!
}
}
class Baz extends Bar {
static void testAsserts() {
boolean enabled = false;
assert enabled = false;
System.out.println("Asserts " +
(enabled ? "enabled" : "disabled"));
}
}
这将打印Asserts disabled Asserts disabled
为Bar
初始化良好。Bar
初始化禁用assert
类,因此禁用Baz
.