I was wondering how assertions were implemented. I found that javac
uses a static field $assertionsDisabled
. And I was curious what will happen if $assertionsDisabled
is already used.
public class Test {
static final boolean $assertionsDisabled = Math.random() < .5;
public static void main(String[] args) {
assert false;
}
}
I expected javac
to use another name instead, just like other cases of automatic name generation. However, ...
C:\Users\...\src>javac -J-showversion Test.java
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
Test.java:1: error: the symbol $assertionsDisabled conflicts with a compiler-syn
thesized symbol in Test
public class Test {
^
Test.java:2: error: the symbol $assertionsDisabled conflicts with a compiler-syn
thesized symbol in Test
static final boolean $assertionsDisabled = Math.random() < .5;
^
2 errors
This lead me to the question: Is this compiler behavior standard-compliant or not? Does the compiler have difficulty to use another name?
First of all, there are (or used to be) far more substantial differences between the behavior of javac and the behavior specified by the JLS than this one. This has been improving over the years, but there are still issues. So no, javac as a whole is not standard-compliant.
Second, the JLS says that the $ sign "should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems." Technically, the code you write is not mechanically generated, so you're not supposed to use the $ character in your variable names.
Finally, the code to choose another name needs to be written, tested and maintained, and I assume the javac development team has found more valuable areas to invest their time in.