Why static final variables are accepted in local classes?

前端 未结 1 1120
情深已故
情深已故 2021-01-22 17:00

I\'ve googled this extensively to no avail. I cannot seem to wrap my head around this concept. Why are static final fields accepted in local classes? Such as the following examp

1条回答
  •  一整个雨季
    2021-01-22 17:23

    It's not, in general.

    But farewell is a special kind of static final: one whose value is a constant, as defined by JLS 15.28. That means that it's not being initialized at that location, which is what's actually disallowed in non-static classes (including local classes), as per JLS 8.1.3.

    The JLS states this explicitly (and in bold font) in 8.1.3 (note the "unless" part):

    It is a compile-time error if an inner class declares a member that is explicitly or implicitly static, unless the member is a constant variable (§4.12.4).

    If you change that line to either remove the final modifier or make the expression non-constant (for example, new String("Bye bye")), then you'll get the compilation error you expect:

    Test.java:5: error: Illegal static declaration in inner class EnglishGoodbye
                public static final String farewell = new String("Bye bye");
                                           ^
      modifier 'static' is only allowed in constant variable declarations
    1 error
    

    A bit more:

    The reason this is allowed is that constant variables are treated specially by the compiler. In particular, it's allowed to inline them -- the resulting bytecode doesn't have the farewell field at all! If you decompile the class (javap -c YourClassName), you'll see something like this:

    public void sayGoodbyeInEnglish();
      Code:
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Bye bye
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         ...
    

    The above corresponds to this line:

    System.out.println(EnglishGoodbye.farewell);
    

    It's a bit daunting, but notice that "3:" line. The program isn't loading the value of the field farewell, it's loading constant #3 (which it note in a comment is the String "Bye bye") (you can see a list of the bytecodes on wikipedia).

    Because farewell is a constant variable (and not a "real" static member), and thus can be inlined in the code, it doesn't matter where you define it -- the variable's lifecycle is essentially that of the whole JVM, not any one class or instance, and thus it can be declared anywhere.

    0 讨论(0)
提交回复
热议问题