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

2022-09-02 10:23:25

可能的重复:
为什么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
}

而我从为什么我们可以有静态的最终成员,但不能在内部类中有静态方法?它可以从其所有者类继承静态成员。但为什么它不应该呢?它伤害了OOP的什么原则?


答案 1

您的类未声明为静态。那么,对于它有一个静态场来说,这究竟意味着什么呢?myInnerClassTest

会不会

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

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

规格

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

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

内部类不能声明静态初始值设定项 (§8.7) 或成员接口,或者发生编译时错误。

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


答案 2

根据JLS: -

8.1.3 内部类和封闭实例

内部类是未显式或隐式声明为静态的嵌套类。内部类不能声明静态初始值设定项 (§8.7) 或成员接口。内部类不能声明静态成员,除非它们是编译时常量字段 (§15.28)。

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

除了这两件事,我觉得很重要。还有更多你可以从那里得到它。有一个关于 、 和 . . 的庞大解释。inner classesanonymous inner classesnested classes

更新说明 : -

想想看。静态块在类初始化期间执行,如果没有封闭类的实例,就无法初始化非静态内部类,这就是原因。

内部类与封闭类的 相关联。它们类似于封闭类的其他实例属性。现在,在上下文中嵌入字段是没有意义的。但是,如果将它们声明为编译时常量,则允许使用它们。instancestaticnon-static

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

另一方面,如果你的内部类是 ,那实际上是一个嵌套类,那么你可以声明你的字段是静态的,因为它们仍然会与类相关联,所以你甚至可以在实例化中封闭类之前访问它们。static

我希望这是有道理的。

更新 2 : -

public class A {
   class B {
        static int x = 0;
   }
}

在上面的代码中,对于类 B 的每个实例都是通用的。此外,的每个实例都将有自己的副本(因为每次创建 a 时,JVM 都必须装入类 B)。static variable xclass Aclass Binstance of A

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

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


推荐