为什么内部类不能使用静态初始化器?

时间:2014-08-23 05:02:06

标签: java inner-classes jls static-initializer

Quoth JLS #8.1.3

  

内部类可能无法声明静态初始值设定项§8.7)......

这证明了这一点:

class A {
    class B {
        static { // Compile-time Error: Cannot define static initializer in inner type A.B
            System.out.println("Class is initializing...");
        }
    }
}

既然Java的内部(非静态)类是由class loaders加载的,就像其他所有类一样,为什么我们不能为它们提供静态初始化器?

这种限制背后的原因是什么?

3 个答案:

答案 0 :(得分:0)

我认为这是因为Inner类本身不是静态的。从Java的角度来看,它是一个实例变量,我认为 (1)类加载器不是设计为爬进内部非静态类来查找和初始化potentiel static对象。

但这不是不可能性问题,请看下面的例子:

public class Outer {
    public static class Inner {
        Outer owner;
        static String constant;

        {
            constant = "foo";
        }

        private Inner(Outer owner) {
            if (owner == null) {
                throw new NullPointerException();
            }
            this.owner = owner;
        }
    }

    public Inner newInner() {
        return new Inner(this);
    }
}

甚至没有警告,因为Inner被声明为静态。

但是第二眼看,它有一个指向封闭Outer实例的指针,只能通过Outer创建,因为它只有一个私有构造函数,并且它的所有者不能为null。从程序员的角度来看,它具有非静态内部类的所有约束,并且可以像一个一样使用(除了Outer.this之类的特殊习惯用法),但从编译器的角度看它是静态的并且它是静态的字段将在第一次Outer类初始化时正确初始化。

(1):Pacerier在下面解释了为什么这是不正确的。

答案 1 :(得分:0)

无有效使用

只是我提出的意见,赞成争论/辩论

请阅读以下主题。

This explains, Why does Java prohibit static fields in inner classes

IMO同样的理由也适用于static initializer。毕竟,创建问题的关键是关键字static

除了上面提到的原因,我还可以给出另一个蹩脚的理由static initializer的名称为我们提供了使用此块的时间和原因的提示。一个不是简单地使用静态初始化块来打印hello world [在这里插入meme ]。
使用此块的主要原因显然是初始化静态变量。

现在内部类/非静态嵌套类不允许使用静态变量,允许静态初始化器有什么意义?

答案 2 :(得分:-1)

根据定义存在矛盾:

来自JLS §8.1.3

  

语句或表达式出现在静态上下文中,当且仅当   最里面的方法,构造函数,实例初始化器,静态   初始化程序,字段初始值设定项或显式构造函数调用   括起语句或表达式的语句是静态方法,a   静态初始化程序,静态变量的变量初始值设定项,或   显式构造函数调用语句(第8.8.7节)。

     

...

     

当一个内部类(其声明不在静态中发生)   context)指的是作为a的成员的实例变量   词汇封闭类,词汇对应的变量   使用封闭实例。