assert
statement JDK 1.8 case study
The assert
statement is an example of construct that generates a static synthetic
field in Oracle JDK 1.8.0_45:
public class Assert {
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
basically compiles to:
public class Assert {
// This field is synthetic.
static final boolean $assertionsDisabled =
!Assert.class.desiredAssertionStatus();
public static void main(String[] args) {
if (!$assertionsDisabled) {
if (System.currentTimeMillis() != 0L) {
throw new AssertionError();
}
}
}
}
This can be verified with:
javac Assert.java
javap -c -constants -private -verbose Assert.class
which contains:
static final boolean $assertionsDisabled;
descriptor: Z
flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
The synthetic field is generated so that Java only needs to call Assert.class.desiredAssertionStatus()
once at load time, and it then caches the result there.
See also: https://mcmap.net/q/63341/-what-are-assertions-in-java-and-when-should-they-be-used for a more detailed explanation.
Note that this synthetic field can generate name conflicts with other fields we may define. E.g., the following fails to compile on Oracle JDK 1.8.0_45:
public class Assert {
static final boolean $assertionsDisabled = false;
public static void main(String[] args) {
assert System.currentTimeMillis() == 0L;
}
}
The only thing that "prevents" that is the naming convention of not using dollars on your identifiers. See also: When should I use the dollar symbol ($) in a variable name?
Bonus:
static final int $assertionsDisabled = 0;
would work, because unlike Java, the bytecode allows multiple fields with the same name but different types: Variables having same name but different type