2013-07-08 107 views
6

我遇到了一個場景,我需要一個公共和一個私人構造函數。需要使用私有構造函數來設置私有類型爲私有內部類的私有字段。 這是被封住還是氣餒?否則對於下面列出的方案,什麼是更好的解決方案?一個類可以有公共和私有構造函數嗎?

請閱讀評論,這更有意義地支持我的問題。謝謝,

public class CopyTree { 
    private TreeNode root; 

    public Copytree() { } 

    // private CopyTree(TreeNode root) { this.root = root; } 

    private static class TreeNode { 
     TreeNode left; 
     TreeNode right; 
     Integer element; 
     TreeNode(TreeNode left, TreeNode right, Integer element) { 
      this.left = left; 
      this.right = right; 
      this.element = element; 
    } 
} 

public CopyTree copyTree() { 
    CopyTree ct = new CopyTree(); 
    ct.root = copyTree(root); // <---- QUESTION: Any cleaner solution ?? 
    // cleaner solution appears to be a private constructor 
    // eg: CopyTree ct = new CopyTree(copyTree(root)); But can public and private constructor  coexist together ? 
    return ct; 
} 

private TreeNode copyTree(TreeNode binaryTree) { 
    TreeNode copy = null; 
    if (binaryTree != null) { 
     copy = new TreeNode(null, null, binaryTree.element); 
     copy.left = copyTree(binaryTree.left); 
     copy.right = copyTree(binaryTree.right); 
    } 
    return copy; 
} 
+2

檢查:http://stackoverflow.com/a/11360712/1544069 – ritesh

+1

你爲什麼不接受一個答案?他們都花時間回覆你的帖子,所以你至少可以做回報。來吧;) – Andy

+1

當然,我的歉意。請留意並感謝整個社區的幫助,同時感謝您的關注。 – JavaDeveloper

回答

0

能否一類具有公共和私有構造?

是的,這是可能的。

需要一個私有構造函數來設置私有的類型是一個私有的內部類。這是鼓勵還是氣餒?

這取決於具體情況。無論你想讓其他課程初始化你的對象的狀態與否。在這裏,我認爲你已經創建了類CopyTree來返回一個私有類的樹副本。所以TreeNode類將被封裝,因此它會讓您選擇使用私有構造函數捕獲習慣用法。

對於下面列出的方案,什麼是更好的解決方案?

在我看來,private構造函數capture成語是更好的解決方案。

欲瞭解更多信息:

您可以搜索private constructor capture idiom

的例子在Java Puzzlers溶液53給出:

謎題53:做你的事

現在輪到你編寫一些代碼。假設你有這個事情,其唯一的構造函數庫類接受一個int參數:

public class Thing {  
    public Thing(int i) { ... } 
     ... 
    } 

事實例提供沒有辦​​法得到它的構造函數參數的值。因爲Thing是一個圖書館類,你不能訪問它的內部,你不能修改它。 假設您想編寫一個名爲MyThing的子類,並帶有一個構造函數,該構造函數通過調用SomeOtherClass.func()方法來計算超類構造函數的參數。此方法返回的值在呼叫之間不可預知地發生變化。最後,假設您想要將傳遞給超類構造函數的值存儲在子類的最終實例字段中以備將來使用。這是你會自然地編寫代碼:

public class MyThing extends Thing { 
    private final int arg; 
    public MyThing() { 
     super(arg = SomeOtherClass.func()); 
     ... 
    } 
    ... 
} 

不幸的是,這是不合法的。如果你嘗試編譯它,你會得到一個看起來像這樣的錯誤消息:

MyThing.java: 
    can't reference arg before supertype constructor has been called 
     super(arg = SomeOtherClass.func()); 
       ^

你怎麼能改寫MyThing達到預期的效果? MyThing()構造函數必須是線程安全的:多個線程可以同時調用它。

溶液53:做你的事

你可以嘗試調用SomeOtherClass.func()在靜態字段的結果藏匿調用構造函數的東西之前。這個解決方案是可行的,但很尷尬。爲了實現線程安全,您必須同步對隱藏值的訪問,這需要難以想象的扭曲。通過使用線程局部靜態字段(java.util.ThreadLocal)可以避免這些扭曲中的一些,但存在更好的解決方案。 首選的解決方案本質上是線程安全的以及優雅。它涉及在MyThing使用第二,私有構造函數的:

public class MyThing extends Thing { 
    private final int arg; 

    public MyThing() { 
     this(SomeOtherClass.func()); 
    } 

    private MyThing(int i) { 
     super(i); 
     arg = i; 
    } 
} 

此解決方案使用的替代構造函數調用。此功能允許類中的一個構造函數鏈接到同一類中的另一個構造函數。在這種情況下,MyThing()鏈接到私有構造函數MyThing(int),該函數執行所需的實例初始化。在私有構造函數中,表達式SomeOtherClass.func()的值已經在參數i中捕獲,並且可以在超類構造函數返回後存儲在最終字段參數中。

0

使用Private 構造函數,可以防止類被其調用者明確實例化。

凡私有構造函數是有用的,只包含靜態實用方法包含

  • 類唯一不變
  • 類型安全枚舉
  • 單身
  • 在那裏他們被證明是

    • 類缺點(不限於以下幾點,名單可能會增加)

      • 沒有公開或受保護建築商的類別不能被 分類。
      • 它們不容易與其他靜態方法區分開來。
    0

    您只能按以下方式使用私有和公共構造函數。但是你不能將兩者都用於沒有參數構造函數或相同的參數類型。

    public class MyClass { 
    private MyClass(){ 
    
    } 
    public MyClass(int i){ 
    
    } 
    } 
    
    0

    從您的已註釋代碼判斷,您已經嘗試過它,它已經工作。因此,我只能確認你的發現:是的,私有構造函數可以與公共方法共存,是的,這似乎是一個更好的解決方案,因爲在接收對新對象的引用之前完成了更多初始化。

    相關問題