2013-05-21 58 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。參數化構造函數:當您嘗試爲具有參數化構造函數的子類創建對象時,需要通過傳遞參數或不傳遞參數,從子類構造函數強制調用父類構造函數:由於父構造函數是私有的,因此也會失敗。

由於子類將具有默認構造函數或參數化構造函數,並且它們不能具有其中的任何一個,所以不能爲具有私有構造函數的父類使用子類。

相關問題