【问题标题】:Java private constructors visibilityJava 私有构造函数可见性
【发布时间】: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 中可以有构造函数。

标签: java constructor private


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

    【讨论】:

    • 请查看其他答案,您的答案与问题无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 2019-08-07
    • 2011-04-20
    • 2010-09-23
    相关资源
    最近更新 更多