I can give a partial explanation to it. It refers to enabling/disabling assertion. Assertion is enabled by -ea
vm argument.
An important point about assert
is:
An assert statement that is executed before its class has completed initialization is enabled.
Suppose -ea
is not given and you run the below code:
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"));
}
}
In the above example when b
is initialized, Java guarantees that before line(a)
is called, the assertion is disabled (i.e. line(a) is not executed at all). Because assert enable/disable is a part of class initalization, hence it is mentioned in your shown statement in question.
The reason, why top-level class is mentioned and not every other class is this. More detailed behavior here:
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"));
}
}
Even -ea
flag is not used, still it throws an AssertionException
. Here is what happens:
- Q1.main is called
- Q1.main calls Baz.testAsserts.
- Because Baz extends Bar and Bar is not initialized, as per JLS it tries to initialize Bar
- static block of Bar is called. Remember assert statement is enabled before its class has completed initialization or assert is called (which ever happens first). Which in this case is
true
at this stage as Bar
is still not completely initialized
- static of
Bar
calls Baz.testAsserts()
. The assert is still enabled (remember disabling assertion has got to do with class initialization and Bar is still not completely initialized). Now Baz.testAsserts() throws AssertionException
.
Above is a loop hole. JLS only guarantees that before executing any assert
in Top level class, it will disable/enable (as whatever vm argument is given) it. But if it is not a top level class, then the behavior depends on the initialization of top-level class. To explain this, see this:
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"));
}
}
This prints Asserts disabled Asserts disabled
as Bar
is well initialized. Bar
initialization disables assert
for the class and hence for Baz
.