Java 使用包私有构造函数继承 public class

Java Inheriting a public class with Package Private Constructor

我有 C++ 背景,我刚刚经历了 Java 中的访问修饰符,我决定尝试一些代码,但现在我收到一个错误:

YouArePublic() is not public in YouArePublic; cannot be accessed from outside package

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

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

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

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

问题是 class 本身不是 public,因此,正如消息所说,无法从包外部访问。只需将其设置为 public,你应该没问题(如你所述,将创建一个默认的 public 构造函数):

public class Tester extends YouArePublic {

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

您的 main-method 可能是静态的,但这仅意味着无需先实例化对象即可调用它。在您的 main-method 中,您正在创建一个对象:

Tester ot = new Tester();

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

public Tester() {
    super();
}

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

访问它

您只能对静态方法进行静态调用。对于那个初始化是不需要的。但是在这里您没有进行静态调用,并且您的父 class 方法不是静态的。为此,您应该如下修改您的父级 class。(但仅此一项不足以编译 class)

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 的对象时,首先调用父 class 的构造函数,然后调用子 class.For 的构造函数编译器,您的代码与下面显示的代码相同。

class Tester extends YouArePublic { 
    public Tester(){
        super();
    }

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

在您的情况下,无法完成对超级构造函数的调用,因为父构造函数的可见性为 'default',并且仅对同一包中的 classes 可见。

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