一般来说,并非如此。
But farewell
是一种特殊的 static Final:其值为常量,定义为JLS 15.28。这意味着它没有在该位置初始化,这实际上是非静态类(包括本地类)中不允许的,根据JLS 8.1.3.
JLS 在 8.1.3 中明确(并以粗体)说明了这一点(注意“除非”部分):
如果内部类声明显式或隐式静态的成员,则会出现编译时错误,除非该成员是常量变量(第 4.12.4 节)。
如果您更改该行以删除final
修饰符或使表达式变得非常量(例如,new String("Bye bye")
),然后你会得到你期望的编译错误:
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
多一点:
允许这样做的原因是编译器会特殊对待常量变量。特别是,它允许内联它们——生成的字节码没有farewell
场根本!如果你反编译该类(javap -c YourClassName
),你会看到这样的东西:
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
...
上面对应这一行:
System.out.println(EnglishGoodbye.farewell);
这有点令人畏惧,但请注意“3:”行。程序未加载该字段的值farewell
,它正在加载常量#3(它在注释中指出是字符串“Bye bye”)(您可以看到字节码列表在维基百科上).
Because farewell
是一个常量变量(而不是“真正的”静态成员),因此可以内联在代码中,无论在哪里定义它,变量的生命周期本质上是整个 JVM 的生命周期,而不是任何一个类的生命周期或实例,因此可以在任何地方声明它。