当前位置: 首页 > 知识库问答 >
问题:

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

姚智
2023-03-14

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

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

共有3个答案

齐承泽
2023-03-14

根据定义,这是自相矛盾的:

根据 JLS §8.1.3:

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

...

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

郭修平
2023-03-14

无效使用

只是我的一个意见,争论/辩论是值得赞赏的

请阅读下面的帖子。

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

在我看来,同样的原因也适用于<code>静态初始值设定项。毕竟,造成问题的是关键字static

除了上面的原因,我还可以给出另一个蹩脚的理由
块的名称静态初始值设定项提示我们何时以及为什么使用此块。我们不能简单地使用静态初始值设定项块来打印hello world[在这里插入模因]
使用此块的主要原因显然是初始化静态变量。

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

贺景山
2023-03-14

我认为是因为内部类本身是非静态的。从Java的角度来看,< del >它是一个实例变量,我认为(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);
    }
}

甚至没有警告,因为内部声明为静态。

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

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

 类似资料:
  • 问题内容: 为什么我们不能在非静态内部类中使用静态方法? 如果我将内部类设为静态,则可以工作。为什么? 问题答案: 因为内部类的实例与外部类的实例隐式关联,所以它本身不能定义任何静态方法。由于静态嵌套类无法直接引用其封闭类中定义的实例变量或方法,因此只能通过对象引用使用它们,因此在静态嵌套类中声明静态方法是安全的。

  • 问题内容: 为什么我们不能在非静态内部类中使用静态方法? 如果我将内部类设为静态,则可以工作。为什么呢 问题答案: 因为内部类的实例与外部类的实例隐式关联,所以它本身不能定义任何静态方法。由于静态嵌套类无法直接引用其封闭类中定义的实例变量或方法,因此只能通过对象引用使用它们,因此在静态嵌套类中声明静态方法是安全的。

  • 问题内容: 为什么我们不能在非静态内部类中使用静态方法? 如果我将内部类设为静态,则它可以工作。为什么? 问题答案: 因为内部类的实例与外部类的实例隐式关联,所以它本身不能定义任何静态方法。由于静态嵌套类无法直接引用其封闭类中定义的实例变量或方法,因此只能通过对象引用使用它们,因此在静态嵌套类中声明静态方法是安全的。

  • 问题内容: Java教程说,由于内部类与封闭类的实例相关联,所以它(内部类)本身不能定义任何静态成员。 对我来说很有趣,为什么内部类不能声明静态成员,例如某个字段,该内部类的实例可能会与同一内部类的其他实例共享这些成员?这仅仅是Java中必须被视为理所当然的事情的实现吗? 问题答案: 基本上只是一个任意决定。我们没有理由也 不可能 得到支持,但还算不上什么好的理由 来 支持它。只需在外部类中声明静

  • 我在旧的遗留系统中找到了这段代码,如果没有任何问题,我不想去碰它。 但是我觉得这段代码有一些缺陷,我找不到它。这是不是常见的模式,还是有一些隐藏的陷阱或内存泄漏? 此代码用于片段 更新:我怀疑匿名内部类的对象引用了父片段,由于该类的对象保存在静态字段中,因此永远不会收集,因此也永远不会收集父片段。我的推理错了吗?

  • 问题内容: Java的设计者是否有任何理由认为不应为局部变量提供默认值?认真地讲,如果实例变量可以被赋予默认值,那为什么我们不能对局部变量做同样的事情呢? 问题答案: 声明局部变量主要是为了进行一些计算。因此,程序员决定设置变量的值,并且不应采用默认值。如果程序员错误地没有初始化局部变量并且使用默认值,则输出可能是一些意外值。因此,在使用局部变量的情况下,编译器将要求程序员在访问变量之前使用一些值