Java 私有构造函数可见性

Posted

技术标签:

【中文标题】Java 私有构造函数可见性【英文标题】:Java private constructors visibility 【发布时间】:2016-02-21 09:16:02 【问题描述】:

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

考虑以下示例:

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),我们可以阅读:

[...]

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

[...]

否则,成员或构造函数被声明为private,并且当且仅当它出现在包含成员或构造函数声明的***类(第 7.6 节)的主体内时才允许访问。

谁能解释一下为什么构造函数可以从C 访问,即使被声明为private

【问题讨论】:

可以调用 super 并不意味着可以访问构造函数 谁能解释为什么构造函数可以从 C 访问,即使被声明为私有? -> 因为 B 和 C 都是 A 的内部类。如果将 B 和 C 移到 A 之外,将不再起作用。 @JörnBuitink:如果是这样,那为什么foo()不可访问?这里似乎确实存在不一致。 请注意super.foo() 有效。 @Arun 那是 C#。不是Java。静态类在 Java 中可以有构造函数。 【参考方案1】:

方法foo()是私有的,所以你不继承它,也不能直接从C类调用。

但是,您可以从 B 看到私有方法和构造函数,因为所有内容都在同一个包含类中声明,并使用 super 访问它们,这就是 super() 起作用的原因。 同理,可以通过super.foo()访问foo

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

【讨论】:

非常感谢您的回答 WilQu 和 @benzonico。这似乎是诀窍。因此我接受你的回答。【参考方案2】:

所以这里的诀窍可能如下:

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

但是,正如 cmets 中所述,您可以访问 super.foo();,因为 super 指的是在同一***类中声明的类型(有关此内容,请参见 JLS 6.6.1)。

然后诀窍是调用super(s) 可以被视为调用super.<init>(s) 最终与super.foo() 相同

【讨论】:

【参考方案3】:

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

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

 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 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。

【讨论】:

请查看其他答案,您的答案与问题无关。

以上是关于Java 私有构造函数可见性的主要内容,如果未能解决你的问题,请参考以下文章

特征可以具有具有私有和受保护可见性的属性和方法吗?特质可以有构造函数、析构函数和类常量吗?

Java 继承:降低构造函数与继承方法的可见性

为啥私有构造函数在案例类中仍然可见?

Java 内部类可见性难题

Java中私有构造函数有啥用?

在java中,如何创建一个具有私有构造函数的类,其超类也有一个私有构造函数?