为什么Java不允许从构造函数为private的类继承?
答案 0 :(得分:23)
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
它阻止的是无法访问其超类的任何构造函数的子类。这意味着私有构造函数不能在另一个类文件中使用,并且包本地构造函数不能在另一个包中使用。
在这种情况下,您唯一的选择是委派。您需要调用工厂方法来创建“超级”类的实例并将其包装起来。
答案 1 :(得分:19)
因为类必须调用其超类构造函数始终。如果无法访问超类构造函数,则无法初始化子类。
更多信息:JLS 8.8.10. Preventing Instantiation of a Class
关于Brian Roach的评论:
对[父类构造函数]的调用仅在您没有显式执行且父项具有公共或受保护的无参数构造函数时才是隐式的(或者没有定义任何情况,在这种情况下,默认情况下没有 - ARG)。这是必需的,因为...这就是语言的运作方式。 Children [classes]必须调用[他们的]父级的构造函数。
请注意,当您在Java中实例化任何类时,始终会对Object
构造函数进行隐式调用,因为它是所有类的超类。它将执行其default constructor:
public Object() {
}
来自JLS链接的注释:
如果默认构造函数被隐式声明为,但是超类没有可访问的构造函数(第6.6节),它不带参数且没有throws子句,那么这是一个编译时错误。
答案 2 :(得分:1)
如果类的构造函数是私有的,那么子类不能调用超级构造函数。 因此继承会失败。
答案 3 :(得分:1)
如果您有子类,则子类(子类)构造函数有2种可能性: 1.默认构造函数(无参数构造函数):在这种情况下,默认构造函数将自动尝试调用父类构造函数:由于父类构造函数是私有的,因此将失败。 2.参数化构造函数:当您尝试为具有参数化构造函数的子类创建对象时,您需要通过传递参数或不传递参数来强制从子类构造函数调用父类构造函数:这也将失败,因为父构造函数是私有的。
由于子类将具有默认构造函数或参数化构造函数,并且不可能具有其中任何一个,因此不能为具有私有构造函数的父类创建子类。
答案 4 :(得分:0)
是的,在Luiggi的回答中添加了一些内容在创建Singleton类时使用了java的这个特性,该类只允许创建该类的一个实例。
答案 5 :(得分:0)
这是因为,当我们继承时,编译器的工作是通过在每个类构造函数的第一条语句中编写super()来使所有类与Object类建立直接或间接关系。 当我们将构造函数设为私有时,这意味着不应从类外部访问它,但是当我们继承时,编译器将隐式编写此类语句。
class SubClassName extends SuperClassName {
public SubClassName() {
super(); // which will indirectly going to call the Parent class constructor from outside its scope
}
}