Java 私有构造函数可见性

2022-09-01 11:01:17

我试图理解为什么在谈论构造函数时类成员的可访问性之间存在差异。

请考虑以下示例:

class A {
  static class B {  
    private B(String s) {}
    private void foo() {}
  }
  static class C extends B {
    public C(String s) {
      super(s); // call B(String), which is private, and obviously accessible
    }
    void bar() {
      foo(); // compilation error (symbol unknown), as B.foo() is private
    }
  }
}

的私有成员作为私有成员,不应从 进行访问。对于字段和方法,情况就是这样,但构造函数似乎不遵循相同的规则。AB

来自 JLS-8 (6.6.1.确定可访问性),我们可以阅读:

[...]

仅当引用类型的成员(类、接口、字段或方法)或类类型的构造函数可访问并且成员或构造函数声明为允许访问时,才能访问该类型:

  • [...]

  • 否则,将声明成员或构造函数,并且当且仅当访问发生在包含成员或构造函数声明的顶级类 (§7.6) 的主体中时,才允许访问。private

谁能解释一下为什么构造函数可以从 访问,即使在声明时也是如此?Cprivate


答案 1

该方法是私有的,因此您不会继承它,也不能直接从类中调用它。foo()C

但是,您可以看到私有方法和构造函数,因为所有内容都在同一个包含类中声明,并使用 访问它们,这就是工作的原因。同样,您可以使用 进行访问。Bsupersuper()foosuper.foo()

请注意,您可以在 中重新定义新的 foo 方法,但此方法不会重写 。CB.foo()


答案 2

所以这里的诀窍可能是这样的:

您无法访问,因为它被声明为私有,因此您不会在C中继承它。foo

但是,正如注释中所指出的,您可以访问,因为引用在同一顶级类中声明的类型(请参阅 JLS 6.6.1)。super.foo();super

然后诀窍是,呼叫可以被视为呼叫,最终与super(s)super.<init>(s)super.foo()