为什么Java不允许从构造函数为私有的类继承?
6 回答
Java 不会阻止使用私有构造函数对类进行子类化。
public class Main {
static class A {
private A() {
System.out.println("Subclassed A in "+getClass().getName());
}
}
static class B extends A {
public B() {
}
}
public static void main(String... ignored) {
new B();
}
}
印刷
Subclassed A in Main$B
它阻止的是无法访问其超类的任何构造函数的子类。这意味着私有构造函数不能在另一个类文件中使用,并且包本地构造函数不能在另一个包中使用。
在这种情况下,您唯一的选择是委派。您需要调用工厂方法来创建“超级”类的实例并包装它。
因为一个类必须总是调用它的超类构造函数。如果无法访问超类构造函数,则无法初始化子类。
更多信息:JLS 8.8.10。防止类的实例化
关于布赖恩·罗奇的评论:
调用 [对父类构造函数] 仅在您没有显式执行并且父类具有公共或受保护的无参数构造函数(或者在这种情况下没有定义任何默认无参数的情况下)时才隐式调用。这是必需的,因为......这就是语言的工作方式。孩子 [类] 必须调用 [他们的] 父母的构造函数。
请注意,当您在 Java 中实例化任何类时,总会隐式调用Object
构造函数,因为它是所有类的超类。它将执行其默认构造函数:
public Object() {
}
JLS 链接中的注释:
如果隐式声明了默认构造函数但超类没有可访问的构造函数(第 6.6 节),该构造函数不接受任何参数并且没有 throws 子句,则这是编译时错误。
如果您有子类,则子类(子类)构造函数有 2 种可能性: 1. 默认构造函数(无参数构造函数):在这种情况下,默认构造函数将自动尝试调用父类构造函数:这将失败,因为父类构造函数是私人的。2. 参数化构造函数:当你尝试为具有参数化构造函数的子类创建对象时,你需要通过传递参数或不传递参数来强制从子类构造函数调用父类构造函数:这也会失败,因为父构造函数是私人的。
由于子类将具有默认构造函数或参数化构造函数,并且不可能拥有它们中的任何一个,因此您不能拥有具有私有构造函数的父类的子类。
如果类的构造函数是私有的,则子类不能调用超级构造函数。因此继承会失败。
Yes adding something to Luiggi's answer this feature of java is used when creating the Singleton classes which allows only one instance of that class to be created.
这是因为,当我们进行继承时,编译器的工作是通过在每个类构造函数的第一条语句中编写 super() 来使所有类与 Object 类建立直接或间接的关系。当我们将构造函数设为私有时,这意味着不应从类外部访问它,但是当我们进行继承时,编译器将隐式编写这种类型的语句。
class SubClassName extends SuperClassName {
public SubClassName() {
super(); // which will indirectly going to call the Parent class constructor from outside its scope
}
}