【问题描述】:

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

考虑以下示例:

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

<1234565>

[...]

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

  • [...]

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

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

【问题讨论】:

  • 可以调用 super 并不意味着构造函数可以访问
  • 谁能解释一下为什么构造函数可以从 C 访问,即使被声明为私有? -> 因为 B 和 C 都是 A 的内部类。如果将 B 和 C 移到 A 之外,将不再起作用。
  • @JörnBuitink:如果是这样,那为什么 foo() not 可以访问?这里似乎确实存在不一致。
  • 请注意 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.(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 访问私有构造函数。如果我们能够初始化或访问私有构造函数,那么创建私有构造函数的意义何在。

    【问题讨论】:

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