非静态内部类中的静态变量

时间:2011-02-12 07:16:02

标签: java static-members inner-classes

首先我想问Why does Java prohibit static fields in inner classes?,但问题已经存在了。 Bozho的回答消除了我给他们需要的原因(serialVersionUID)。但是,我仍然很好奇:

是否仅在源代码或类文件中禁止静态字段?

是的,一个令人信服的理由,为什么禁止这种行为还有待发明。在C中,即使在函数内部也允许使用静态变量。它们的寿命与任何其他静态变量相同,只是它们的可见性不同。同样适用于Java。

3 个答案:

答案 0 :(得分:5)

内部类可以定义静态字段:

  

内部类可能不会声明静态成员,除非它们是编译时常量字段(第15.28节)。

因此,您可以定义序列版本ID。

当静态字段不是常量时,则逻辑不被允许 - 静态字段不需要类的实例 - 它们是每个类,而内部类需要拥有类的实例 - 它们不能存在一个实例。虽然它可能是静态字段是内部类被定义为好像它们在拥有类中,但它会更加混乱。

答案 1 :(得分:3)

如果设计允许静态内容,那么会发生什么不好的事情。在类文件级别没有问题,我认为,字节代码没有内部类的概念。

但这会令人困惑:

class X
    class Y
        static int z;

X x1 = new X();
X.Y y1 = x1.new Y();    

X x2 = new X();
X.Y y2 = x2.new Y();    
X.Y y3 = x2.new Y();    

直观地,y2y3应该共享相同的z,但它应该与z看到的y1相同吗?


从概念上讲,内部类仅在外部实例中有效。甚至可以想象,当外部实例是GC时,JVM会将其卸载; [1]中针对类卸载给出的参数不适用,因为内部类没有静态变量或静态初始化器。

然而现实是,无论外部实例如何,所有内部实例都共享一个类。这当然是正确的:y1.getClass()==y2.getClass()==y3.getClass()

可以说,语言规范规定它是真的:[2]

  

两个引用类型是相同的运行时类型,如果...由同一个类加载器定义,并且具有相同的二进制名称

y1的类和y2的类具有相同的类加载器,X.Y的二进制名称定义良好且独立于外部实例。所以y1和y2必须具有相同的运行时类。

如果语言规范实际上暗示内部类独立于外部实例,则内部类中对静态状态的普遍接受的解释被削弱。


[1] http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

[2] http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.4

答案 2 :(得分:1)

静态成员不允许仅在非静态内部类的情况下,bcz非静态内部类也充当外部类的方法,因此所有方法规则都适用于内部类。我们可以在静态内部声明静态成员类.....

基本规则

  1. 非静态内部类不允许静态方法静态内部类
  2. 静态内部类允许从静态到非静态的所有内容