5

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 的内部(非静态)类像其他所有类一样由类加载器加载,为什么我们不能为它们设置静态初始化器呢?

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

4

3 回答 3

0

我认为这是因为 Inner 类本身是非静态的。从 Java 的角度来看它是一个实例变量,我想(1)类加载器并非旨在爬入内部非静态类以查找和初始化潜在的静态对象。

但这不是不可能的问题,请看以下示例:

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因为它只有一个私有构造函数,并且它的所有者不能为空。从程序员的角度来看,它具有非静态内部类的所有约束,可以像一个一样使用(除了特殊的习惯用法,如Outer.this),但从编译器的角度来看,它是静态的,它的静态字段将是正确的在第一Outer类初始化时初始化。

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

于 2014-08-23T08:29:50.657 回答
0

没有有效使用

只是我的意见,争论/辩论表示赞赏

请阅读以下主题。

这解释了为什么 Java 禁止内部类中的静态字段

IMO 同样的理由也适用于static initializer. 毕竟,产生问题的东西是关键字static

除了上面线程中解释的原因之外,我还可以给出另一个蹩脚的原因
块的名称static initializer提示我们何时以及为何使用该块。不能简单地使用静态初始化程序块来打印 hello world [在此处插入 meme ]。
使用这个块的主要原因显然是初始化静态变量。

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

于 2016-09-09T12:14:17.300 回答
-1

定义上存在矛盾:

JLS §8.1.3

当且仅当包含语句或表达式的最内层方法、构造函数、实例初始化程序、静态初始化程序、字段初始化程序或显式构造函数调用语句是静态方法、静态初始化程序、变量初始化程序时,语句或表达式才会出现在静态上下文中静态变量或显式构造函数调用语句(第 8.8.7 节)。

...

当内部类(其声明不在静态上下文中)引用作为词法封闭类成员的实例变量时,使用相应的词法封闭实例的变量。

于 2014-08-23T05:13:42.207 回答