Java 私有构造函数可见性

Java private constructors visibility

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

考虑以下示例:

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
    }
  }
}

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

从JLS-8 (6.6.1. Determining Accessibility),我们可以读到:

[...]

A member (class, interface, field, or method) of a reference type, or a constructor of a class type, is accessible only if the type is accessible and the member or constructor is declared to permit access:

  • [...]

  • Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

任何人都可以解释为什么构造函数可以从 C 访问,即使在声明 private 时也是如此?

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

但是,您可以从 B 中看到私有方法和构造函数,因为所有内容都在包含 class 的同一文件中声明,并使用 super 访问它们,这就是为什么 [=14] =] 有效。 同理,可以用super.foo().

访问foo

请注意,您可以在 C 中重新定义一个新的 foo 方法,但此方法不会覆盖 B.foo()

所以这里的技巧可能如下:

您无法访问 foo,因为它被声明为私有的,所以您不能在 C 中继承它。

但是,如评论中所述,您可以访问 super.foo();,因为 super 指的是在同一顶级 class 中声明的类型(请参阅 JLS 6.6.1这个)。

那么诀窍是调用 super(s) 可以被视为调用 super.<init>(s) 最终与 super.foo()

相同

Foo() 方法在 class C 中不可访问,因为 foo() 方法是私有的,私有方法不能继承到基础 class.

对于构造函数,构造函数永远不会被继承。另外,我编译了这段代码:

 class Vehicle{  
        int speed=50;  
        private Vehicle()
        {
           System.out.println("Private Vehicle constructor");
        }
    } 
    public class Bike4 extends Vehicle{  
        int speed=100;   
    Bike4()
    {
        super();
         System.out.println("Hi I n constructor");
    }
  void display(){  
   System.out.println(super.speed);//will print speed of Vehicle now  
  }  
  public static void main(String args[]){  
   Bike4 b=new Bike4();  
   b.display();  

}  
}  

并得到编译时错误:Vehicle() 在 Vehicle 中具有私有访问权限 极好的(); ^ 这清楚地表明不能使用 super 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。