为什么 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 中使用它因为它不违反编译规则。
现在,为什么它不违反编译规则,因为当你声明一个常量变量并初始化它时,编译器可以确定地说这将是这个变量的值,而如果你不初始化它,那么编译器就不能确定说这将是这个变量的值,并且不确定它是否可以在运行时修改,并且一旦分配它就不能更改最终值。
中与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.
我们已经明白非静态内部 类 不能有任何带有 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 中使用它因为它不违反编译规则。
现在,为什么它不违反编译规则,因为当你声明一个常量变量并初始化它时,编译器可以确定地说这将是这个变量的值,而如果你不初始化它,那么编译器就不能确定说这将是这个变量的值,并且不确定它是否可以在运行时修改,并且一旦分配它就不能更改最终值。
中与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 withfinal
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.