为什么静态字段(不是final)在java中的内部类中受到限制

Vir*_*dra 20 java static-members inner-classes

可能重复:
为什么Java禁止内部类中的静态字段?

我正在通过规范并得到内部类中的静态成员不可能是最终编译时间常量.

class HasStatic {
    static int j = 100;
}
class myInnerClassTest {
    class Inner extends HasStatic {
        static final int x = 3;  // OK: compile-time constant
        static int y = 4;  // Compile-time error: an inner class
    }
    static class NestedButNotInner{
        static int z = 5;    // OK: not an inner class
    }
    interface NeverInner {}   // Interfaces are never inner
}
Run Code Online (Sandbox Code Playgroud)

虽然我得到了为什么我们可以拥有静态最终成员但是在内部类中不能使用静态方法?它可以从其所有者类继承静态成员.但为什么不应该呢?OOP的主要伤害是什么?

Den*_*ret 12

您的类myInnerClassTest未声明为静态.那么它具有静态字段究竟意味着什么呢?

可不可能是

  • 对于所有实例,无论封闭实例是什么?
  • 对于具有相同封闭实例的此内部类的所有实例,它们是否相同?

乍一看,大多数程序员可能认为这是第一种情况,而(非静态)内部类的封装逻辑应该可能导致第二种选择.无论是哪种情况(或两者都有不同的修饰语)都需要一个新的定义,static其中可能没有必要.在任何一种情况下,程序员都会对确切的含义感到困惑.

规格:

内部类是未显式或隐式声明为静态的嵌套类.

内部类包括本地(§14.3),匿名(§15.9.5)和非静态成员类(§8.5).

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

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

  • 问题是两个不同的封闭实例的内部类的实例应该被视为在不同的世界中,有点像两个不同的jvm中"相同"类的实例是不同的(以不同的方式查看顶部的Wormbo的注释)说同样的事情).您创建一个非静态内部类,因为您希望将您的类封装并专用于封闭实例,因此它们不应共享变量.当然你的选择也是有道理的,这就是为什么我认为这会令人困惑. (4认同)
  • @AdamDyga“*我会选择“对于所有实例都相同,无论封闭实例如何”。这行不通吗?*”它确实行得通。从 JDK 16 开始。 (2认同)

Roh*_*ain 10

根据JLS: -

8.1.3内部类和封闭实例

内部类是未显式或隐式声明为静态的嵌套类.内部类可能不会声明静态初始化器(第8.7节)或成员接口.内部类可能不会声明静态成员,除非它们是编译时常量字段(第15.28节).

使用但未在内部类中声明的任何局部变量,形式方法参数或异常处理程序参数必须声明为final.任何在内部类中使用但未声明的局部变量必须在内部类的主体之前明确赋值(第16节).

除了这两件事,我发现很重要.有更多的,你可以从那里得到它..有大约一个巨大的解释inner classes,anonymous inner classesnested classes..

更新说明: -

考虑一下.静态块在类初始化期间执行,如果没有封闭类的实例,则无法初始化非静态内部类,这就是原因.

内部类与instance封闭类相关联.它们就像封闭类的其他实例属性一样.现在,staticnon-static上下文中嵌入字段没有意义..但是,如果将它们声明为编译时他们将被允许的常数.

注意: - static final Object = null 不是编译时常量 ..所以,你不能把它们放在你的内部类中

另一方面,如果您的内部类已经存在static,那实际上是一个嵌套类,那么您可以将您的字段声明为静态,因为它们仍将与该类关联,因此您甚至可以在实例化之前封闭类之前访问它们.

我希望这是有道理的..

更新2: -

public class A {
   class B {
        static int x = 0;
   }
}
Run Code Online (Sandbox Code Playgroud)

在上述代码中,static variable x将B类的每个实例共同..此外,的每个实例class A,将具有它自己的副本class B(由于JVM必须装载类B.每次一个instance of A被创建)..

因此,除非它是一个编译时间常量,否则static variable x不能在每个实例之间共享class A.(为了使它更直接: - 你可以做 - B.x如果你看到B作为外部类......但是B类本身是不同的A类的每个实例.因此,B.x对于A类的每个实例,它们将是不同的.因此,静态变量x实际上并不在A类的不同实例之间共享.对静态变量没有意义.)

我希望现在,这是有道理的..