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

时间:2017-05-24 13:15:41

标签: java 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.

3 个答案:

答案 0 :(得分:2)

关于内部类中静态/非静态成员的使用规则,请阅读以下JLS section (§8.1.3)

  

内部类可能不会声明静态初始化器(第8.7节)或成员   接口,或发生编译时错误。

     

内部类可能不会声明静态成员,除非它们是常量   变量(§4.12.4),或发生编译时错误。

请注意上面这一行 - “除非它们是常数变量”,它会回答您的问题。当您将基元或字符串声明为public static final时,它将变为“常量变量”,因此您可以在非静态内部类中使用它,因为它不会破坏它编制规则。

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

在此JLS section (§4.12.4)

中读取与最终变量相关的规则

答案 1 :(得分:1)

  

我们已经明白,非静态内部类不能包含任何具有static关键字的成员。

显然你的理解并不完整。 JLS版本8的8.1.3节部分指定了

  

如果内部类声明显式或隐式静态的成员,则该编译时错误,除非该成员是常量变量(§4.12.4)。

(强调补充。)因此内部类可以拥有静态成员;对他们有相当强烈的限制。

  

但是我们看到,static成员变量final正在被使用和鼓励。任何人都可以解释原因吗?

(原文中的重点。)我认为我经常看不到这种用法,本身。然而,这是保持这些常数范围缩小的明智方法,这是一种很好的做法。

您还要询问为什么static final内部成员无法初始化为null。我不能提供理由,但实际规则在JLS中,在4.12.4节中的“常量变量”(由前面的摘录引用)的定义中详细说明:

  

常量变量是基本类型或类型的最终变量   String用常量表达式初始化(​​§15.28)。

当然,这取决于the definition of a "constant expression",整体呈现有点冗长。它归结为原始或String类型的表达式,它只涉及整数文字,字符串文字,指定常量变量的名称以及相当大的Java运算符子集。这就是我们的观点: null既不是原始类型也不是类型String,因此它不能出现在常量表达式 中,因此,如果变量具有null或包含null的表达式作为其初始值,则变量不是“常量变量”。这样的变量,不是常量变量,不能出现在内部类中。

答案 2 :(得分:0)

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