Why static final variables are accepted in local classes?

房东的猫 提交于 2019-12-02 01:55:00

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!