What does "T is a top-level class, and an assert statement lexically nested within T is executed." mean?
java
Solution
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`.
Problem
I am learning the " Initialization of Classes and Interfaces", and it says "T is a top-level class, and an assert statement lexically nested within T is executed." Could any one tell me what does "T is a top-level class, and an assert statement lexically nested within T is executed." mean by a example? This sentence is from JLS, and original text is like this : A class or interface type T will be initialized immediately before the first occurrence of any one of the following: - T is a class and an instance of T is created. - T is a class and a static method declared by T is invoked. - A static field declared by T is assigned. - A static field declared by T is used and the field is not a constant variable (§4.12.4). - T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed.