2013-05-21 61 views

回答

21

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 

什么它阻止是不能访问其超类的任何构造子类。这意味着一个私有构造函数不能在另一个类文件中使用,并且一个包本地构造函数不能在另一个包中使用。

在这种情况下,您唯一的选择就是委派。您需要调用工厂方法来创建“超级”类的实例并包装它。

+0

有什么不对?实例化一个嵌套的静态类?它是如何工作的? – Jaxox

+0

@jaxox给jvm,嵌套类没什么特别的。他们就像任何其他有更多元信息的课程。所以你可以创建一个被定义为与其他任何方式相同的类。顺便说一句,静态方法中的匿名类也是静态嵌套类。 –

+0

@PeterLawrey我有点得到你在说什么,但我仍然有些困惑。你不是说Java不允许子类无法访问各自的超类构造函数吗?那么在你的例子中,B类不能访问A的构造函数。那么这是如何允许的? – Grateful

18

因为一个类必须调用它的超类构造函数总是。如果超类构造函数不能被访问,那么子类就不能被初始化。

更多信息:JLS 8.8.10. Preventing Instantiation of a Class


关于布莱恩·罗奇的评论:

调用[父类的构造函数]只是,如果你不这样做明确的暗示和家长有一个公共或受保护的无参数构造函数(或者没有定义任何情况下有一个默认的无参数)。这是必需的,因为......这就是语言的工作原理。儿童[班级]必须致电父母的建设者。

注意,当你在Java中实例化任何类,总有到Object构造一个隐式调用,因为它是超类的所有类的。从JLS链接

public Object() { 
} 

注:这将执行其default constructor

这是一个编译时错误,如果默认的构造函数是隐式声明但超类没有可访问的构造 (第6.6节),不带任何参数,也没有引发子句。

+0

为什么这是一个必要的条件,即使它是隐含的? – CodeBlue

+1

如果父类声明了一个私有构造函数,那么它就没有任何含义。这需要在孩子中进行明确的调用,但因为构造函数是私人的,所以你不能。 –

+0

除非您自己指定一个,否则在每个构造方法中都会隐式调用super()。 – cogsmos

1

如果一个类的构造函数是私有的,那么子类不能调用超级构造函数。 因此继承会失败。

0

是的,在Luiggi的答案中增加了一些东西,这个特性在创建Singleton类时使用了,这个类只允许创建一个类的实例。

+1

如果您正确创建单身人士,则不需要。 –

+0

@布赖恩可以请你告诉我如何正确地做到这一点,而不使构造函数是私人的? –

+2

Josh Bloch,'Effective Java second edition' - 使用'enum'。请参阅:http://stackoverflow.com/questions/5759596/the-best-singleton-pattern-since-java-5。如果你没有那本书,就买它。这是一个必须阅读的人认真对待java –

1

如果你有一个子类,你有2个子类(子类)构造函数的可能性: 1.默认构造函数(无参数构造函数):在这种情况下,默认构造函数会自动尝试调用父类构造函数:因为父类的构造函数是私有的。 2。参数化构造函数:当您尝试为具有参数化构造函数的子类创建对象时,需要通过传递参数或不传递参数,从子类构造函数强制调用父类构造函数:由于父构造函数是私有的,因此也会失败。

由于子类将具有默认构造函数或参数化构造函数,并且它们不能具有其中的任何一个,所以不能为具有私有构造函数的父类使用子类。

相关问题