【问题标题】:Java Inheriting a public class with Package Private ConstructorJava使用包私有构造函数继承公共类
【发布时间】:2017-06-19 08:52:27
【问题描述】:

我来自 C++ 背景,我只是在使用 Java 中的 Access-Modifiers,我决定尝试一些代码,但现在我遇到了一个错误:

YouArePublic() 在 YouArePublic 中不公开;无法从 外包装

我不知道为什么。我知道 YouArePublic 类中的构造函数是默认的,因此我无法在它自己的包之外的任何其他类中创建它的对象,但我并没有真正在这里创建对象。

编译器是否隐式尝试创建 Tester 类的对象,从而调用其默认的无参数构造函数,然后使用 super() 调用其超类 YouArePublic 的构造函数?但是 main() 是静态的,所以它不需要创建类的实例来调用它。

我不确定这里发生了什么,真的需要一些帮助。

package one;

import two.YouArePublic;

class Tester extends YouArePublic { // Inheritance in different package
    public static void main(String args[]) {

        Tester ot = new Tester();
        ot.displayMessage();

    }
}


package two;

public class YouArePublic {
    String message = "You are public in package TWO!";

    YouArePublic() { super(); }


    public void displayMessage() {
        System.out.println(message);
    }    
}

【问题讨论】:

    标签: java inheritance visibility


    【解决方案1】:

    问题是类本身不是公共的,因此,正如消息所说,不能从包外部访问。只需将其公开,就可以了(如您所述,将创建一个默认的公共构造函数):

    public class Tester extends YouArePublic {
    

    【讨论】:

    • 能否请您解释一下为什么我需要将 Tester 公开?我在 Tester 中访问 YouArePublic,它是公开的,所以我可以在包 1 中访问它。
    【解决方案2】:

    您的主方法可能是静态的,但这仅意味着可以在不先实例化对象的情况下调用它。在您的主要方法中,您正在创建一个对象:

    Tester ot = new Tester();
    

    如果您自己没有显式定义构造函数,编译器会使用 super() 调用生成隐式默认构造函数,这是对的。它看起来像这样:

    public Tester() {
        super();
    }
    

    这意味着它会尝试调用您的构造函数YouArePublic() { super(); },它具有默认可见性,也就是包私有。由于YouArePublic在另一个包中,所以无法从Tester访问。

    【讨论】:

    • 非常感谢!不知何故,我忽略了 Tester ot = new Tester()。
    【解决方案3】:

    就像你解释的那样,构造函数必须是 public 否则你不能调用它并且类 Tester 不能被实例化。

    【讨论】:

      【解决方案4】:

      您只能对静态方法进行静态调用。因为不需要初始化。但是在这里,您不是在进行静态调用,而且您的父类方法也不是静态的。为此,您应该如下修改您的父类。(但仅此一项不足以编译该类)

      package one;
      
      import two.YouArePublic;
      
      class Tester extends YouArePublic { // Inheritance in different package
          public static void main(String args[]) {    
              Tester.displayMessage();   //No object created 
          }
      }   
      
      package two;
      
      public class YouArePublic {
          String message = "You are public in package TWO!";
      
          YouArePublic() { super(); }    
      
          public void static displayMessage() { //static modifier added
              System.out.println(message);
          }    
      }
      

      例外原因: 创建子类的对象时,首先调用父类的构造函数,然后调用子类的构造函数。对于编译器,您的代码与下面的代码相同。

      class Tester extends YouArePublic { 
          public Tester(){
              super();
          }
      
          public static void main(String args[]) {
              Tester ot = new Tester();
              ot.displayMessage();    
          }
      }
      

      在您的情况下,无法完成对超级构造函数的调用,因为父构造函数的可见性是“默认”并且仅对同一包中的类可见。

      如果您不向父类添加任何构造函数,编译器会假定它具有公共默认构造函数。您通过创建自己的构造函数来限制这一点。

      【讨论】:

        猜你喜欢
        • 2019-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多