为什么 Java 允许静态变量在非静态内部 类 中是 FINAL

Why does Java allow static variables which are FINAL in non-static inner classes

我们已经明白非静态内部 类 不能有任何带有 static 关键字的成员。然而我们看到,static成员变量final正在被使用和鼓励。谁能解释一下为什么?

另一个观察:

final static String abc = "I Love Food"; //works fine

鉴于:

final static String abc = null; //is discouraged and gives error.

如果您查看此已接受的答案 Why does Java prohibit static fields in inner classes,参考部分将为您提供答案。 final static 字段被视为 Java 的编译时间常数。

阅读以下 JLS section (§8.1.3) 以了解有关在内部 class.

中使用 static/non-static 成员的规则

Inner classes may not declare static initializers (§8.7) or member interfaces, or a compile-time error occurs.

Inner classes may not declare static members, unless they are constant variables (§4.12.4), or a compile-time error occurs.

注意上面这一行 - "unless they are constant variables",它回答了您的问题。当您将基元或字符串声明为 public static final 时,它会变成“常量变量”,因此您可以在非静态内部 class 中使用它因为它不违反编译规则。

现在,为什么它不违反编译规则,因为当你声明一个常量变量并初始化它时,编译器可以确定地说这将是这个变量的值,而如果你不初始化它,那么编译器就不能确定说这将是这个变量的值,并且不确定它是否可以在运行时修改,并且一旦分配它就不能更改最终值。

阅读此JLS section (§4.12.4)

中与final变量相关的规则

We already do understand that non-static inner classes cannot have any member which has a static keyword with it.

看来你的理解还不完整。 JLS 版本 8 的第 8.1.3 部分指定,

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).

(强调已添加。)因此内部 class 可以 具有静态成员;只是对它们有相当严格的限制。

Yet we see, static member variables with final is being used and encouraged. Can anyone explain why?

(强调在原文中。)我不认为我经常看到这种用法被鼓励,本身。尽管如此,将此类常量的范围缩小是一种明智的方法,这是一种很好的做法。


你还问为什么static final内部class成员不能初始化为null。我无法为此提供基本原理,但 JLS 中第 4.12.4 节中 "constant variable" 的定义(由前面的摘录引用)详细说明了实际规则:

A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).

当然,这取决于the definition of a "constant expression",完整呈现有点冗长。它归结为原始或 String 类型的表达式,仅涉及整数文字、字符串文字、指定常量变量的名称以及 Java 运算符的相当大的子集。这让我们明白了一点:null既不是基本类型也不是String类型,因此它不能出现在常量表达式,因此如果变量具有 null 或包含 null 的表达式作为其初始值设定项,则它不是 "constant variable"。这样的变量,不是常量变量,不能出现在内部 class.