为什么在java的内部类中限制静态字段(不是final)
可能重复:
为什么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 }
虽然我得到了为什么我们可以拥有静态最终成员但是在内部类中不能使用静态方法? 它可以从其所有者类inheritance静态成员。 但为什么不应该呢? OOP的主要伤害是什么?
您的类myInnerClassTest
未声明为static。 那么它具有静态字段究竟意味着什么呢?
可不可能是
- 对于所有实例,无论封闭实例是什么?
- 对于具有相同封闭实例的内部类的所有实例,它们是一样的吗?
乍一看,大多数程序员可能认为这是第一种情况,而(非静态)内部类的封装逻辑应该可能导致第二种选择。 无论是哪种情况(或两者都有不同的修饰符)都需要一个新的static
定义,这可能不是必要的。 在任何一种情况下,程序员都会对确切含义感到困惑。
从规格 :
内部类是未显式或隐式声明为静态的嵌套类。
内部类包括本地(§14.3),匿名(§15.9.5)和非静态成员类(§8.5)。
内部类可能不会声明静态初始化器(第8.7节)或成员接口,或者发生编译时错误。
内部类可能不会声明静态成员,除非它们是常量变量(第4.12.4节),否则会发生编译时错误。
根据JLS : –
8.1.3内部类和封闭实例
内部类是未显式或隐式声明为静态的嵌套类。 内部类可能不会声明静态初始化器(第8.7节)或成员接口。 内部类可能不会声明静态成员,除非它们是编译时常量字段(第15.28节)。
使用但未在内部类中声明的任何局部变量,forms方法参数或exception处理程序参数必须声明为final。 任何在内部类中使用但未声明的局部变量必须在内部类的主体之前明确赋值(第16节)。
除了这两件事 ,我觉得很重要。还有很多,你可以从那里得到它..有关inner classes
, anonymous inner classes
和nested classes
的巨大解释..
更新解释 : –
考虑一下。 静态块在类初始化期间执行,如果没有封闭类的实例,则无法初始化非静态内部类,这就是原因。
内部类与封闭类的instance
相关联。它们就像封闭类的其他实例属性一样。现在,在non-static
上下文中嵌入static
字段是non-static
意义的。但是,如果你将它们声明为Compile Time Constants,它们将被允许。
注意 : – static final Object = null
不是编译时常量 ..所以,你不能将它们放在你的内部类中
另一方面,如果你的内部类是static
,那实际上是一个嵌套类,那么你可以声明你的字段是静态的,因为它们仍然会与类相关联,所以你甚至可以在实例化之前封闭类之前访问它们。
我希望这是有道理的..
更新2 : –
public class A { class B { static int x = 0; } }
在上面的代码中, static variable x
对于类B的每个实例都是通用的。而且, class A
每个实例都将拥有它自己的class B
的副本(因为每次 instance of A
的instance of A
时 JVM都必须加载B类)被建造)..
因此, static variable x
不能在class A
每个实例之间共享,除非它是编译时常量。(为了使它更直接 : – 你可以做 – 如果你看到B作为外类,则为Bx
..但是对于类A的每个实例,类B本身是不同的。因此,对于类A的每个实例, Bx
将是不同的 。因此,静态变量x
实际上不是在类A的不同实例之间共享。对于一个没有意义静态变量。)
我希望现在,这是有道理的..
所有限制都记录在JLS#8.1.3中。 内部类和封闭实例
因为静态声明与Class相关联,如果在内部类中声明它,它将与实例而不是类相关联。
非静态内部类是Object的成员。 对于成员初始化,仅在创建对象实例时发生。 如果允许静态变量,那么在创建实例之前就会发生初始化。
这就是为什么有单独的non-static
和static
内部类。
您总是需要外部类实例来访问内部类Outer.Inner
只有exception是static inner class
,没有适用于非静态内部类的约束。
static class Inner { static final int x = 3; // OK: compile-time constant static int y = 4;// OK static class NestedButNotInner {// OK } interface NeverInner {// OK }; }
但是允许使用常量,并在JLS中记录
因为内部类与顶级类密切相关,所以必须有一个外部类的实例来创建内部通道
Outer o = new Outer(); Inner i = o.new Inner();
因此,这与实例相关联,而不是与类相关联。
如您所知,内部类可以从其所有者类inheritance静态成员。
class HasStatic { static int j = 100; } class myInnerClassTest { class Inner extends HasStatic { } public static void main(String[] args){ System.out.println(Inner.j); } }
它打印“100”。