Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "T is a top-level class, and an assert statement lexically nested within T is executed." mean?

Tags:

java

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.
like image 598
huashui Avatar asked Jul 23 '13 03:07

huashui


People also ask

What are asserts in Java?

An assertion is a statement in the JavaTM programming language that enables you to test your assumptions about your program. For example, if you write a method that calculates the speed of a particle, you might assert that the calculated speed is less than the speed of light.

What is the most common type of syntax for an assertion?

AssertEquals, AssertTrue, and AssertFalse methods are the most commonly used assertions in selenium. Generally assertions verifies whether the application is same or not when we check with our expectation. Selenium assertions are of three types. In the above syntax it returns Result , if the condition True.


2 Answers

This is a top level class:

class TopLevel {
   ...
}

This is an assert statement:

assert( condition );

where condition is some boolean expression.

A is lexically nested into B, if it occurs inside the curly braces of B's definition. For example, fields, methods, static blocks are lexically nested in a class definition. Statements are lexically nested in methods or static blocks. Local definitions are nested in methods or blocks, that are itself nested in methods.

Hence an assert statement that is lexically nested in a top level class could be:

class A {
    static {
        assert ( 2+2 == 4 );
    }
}
like image 28
Ingo Avatar answered Sep 19 '22 19:09

Ingo


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:

  1. Q1.main is called
  2. Q1.main calls Baz.testAsserts.
  3. Because Baz extends Bar and Bar is not initialized, as per JLS it tries to initialize Bar
  4. 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
  5. 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.

like image 118
Jatin Avatar answered Sep 23 '22 19:09

Jatin