2013-07-08 21 views
6

Mi sono imbattuto in uno scenario, in cui ho bisogno di un costruttore pubblico e privato. È necessario un costruttore privato per impostare il campo privato il cui tipo è una classe interna privata. È incantato o scoraggiato? Altrimenti qual è la soluzione migliore per uno scenario elencato di seguito?Una classe può avere un costruttore sia pubblico che privato?

Si prega di leggere il commento, che supporta la mia domanda in modo più significativo. Grazie,

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

Verifica questo: http://stackoverflow.com/a/11360712/1544069 – ritesh

+1

Perché non accetti una risposta? Hanno preso tutto il loro tempo per rispondere al tuo post, quindi è il minimo che potresti fare in cambio. Andiamo;) – Andy

+1

Certo, mi scuso. Terrò in nota e ringrazio tutta la comunità per l'aiuto, anche grazie per averlo segnalato alla mia attenzione. – JavaDeveloper

risposta

0

Può una classe avere sia costruttore pubblico e privato?

Sì, è possibile.

Un costruttore privato è necessario per impostare il campo privato il cui tipo è una classe interna privata. Questo è incoraggiato o scoraggiato?

Dipende dalla situazione. Se vuoi che l'altra classe inizializzi lo stato del tuo oggetto o meno. Qui penso che tu abbia creato la classe CopyTree per restituire la copia dell'albero che è una classe privata. Quindi la classe TreeNode sarebbe incapsulata, quindi ti lascia con l'opzione di usare l'idioma di acquisizione del costruttore privato.

qual è la soluzione migliore per uno scenario elencato di seguito?

A mio avviso privato idioma cattura costruttore è la soluzione migliore.

Per maggiori informazioni:

è possibile cercare private constructor capture idiom.

Un esempio è dato in Solution 53 Java Puzzlers:

Puzzle 53: Do Your Thing

Ora è il tuo turno di scrivere del codice. Si supponga di avere una classe libreria chiamata Thing cui costruttore unica accetta un parametro int:

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

esempio una cosa non fornisce alcun modo per ottenere il valore del suo parametro del costruttore. Poiché Thing è una classe di libreria, non hai accesso ai suoi interni e non puoi modificarla. Supponiamo di voler scrivere una sottoclasse chiamata MyThing, con un costruttore che calcola il parametro sul costruttore della superclasse richiamando il metodo SomeOtherClass.func(). Il valore restituito da questo metodo cambia in modo imprevedibile da chiamata a chiamata. Infine, si supponga di voler memorizzare il valore passato al costruttore della superclasse in un campo di istanza finale della sottoclasse per uso futuro. Questo è il codice che si sarebbe naturalmente scrive:

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

Purtroppo, non è legale.Se si tenta di compilarlo, si otterrà un messaggio di errore simile a questa:

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

Come si può riscrivere MyThing per ottenere l'effetto desiderato? Il costruttore MyThing() deve essere thread-safe: più thread possono richiamarlo contemporaneamente.

Soluzione 53: Do Your Thing

Si potrebbe provare a riporre il risultato dell'invocazione SomeOtherClass.func() in un campo statico prima di invocare il costruttore Thing. Questa soluzione è praticabile ma scomoda. Per raggiungere la sicurezza del thread, è necessario sincronizzare l'accesso al valore nascosto, che richiede contorsioni inimmaginabili. Alcune di queste contorsioni possono essere evitate usando un campo statico thread-local (java.util.ThreadLocal), ma esiste una soluzione molto migliore. La soluzione preferita è intrinsecamente thread-safe ed elegante. Essa implica l'uso di secondo costruttore, privato in MyThing:

public class MyThing extends Thing { 
    private final int arg; 

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

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

Questa soluzione utilizza un costruttore invocazione alternativo. Questa funzione consente a un costruttore di una classe di collegarsi a un altro costruttore nella stessa classe. In questo caso, MyThing() si collega al costruttore privato MyThing (int), che esegue l'inizializzazione dell'istanza richiesta. All'interno del costruttore privato, il valore dell'espressione SomeOtherClass.func() è stato catturato nel parametro i e può essere memorizzato nel parametro del campo finale dopo il ritorno del costruttore della superclasse.

0

A una classe può essere impedito di essere istanziato in modo esplicito dai chiamanti utilizzando i costruttori privati ​​ .

Dove i costruttori privati ​​sono utili,

  • classi che contengono solo i metodi di utilità statici
  • classi che contengono solo costanti
  • tipo enumerazioni sicuri
  • singletons

quando esso risulti essere uno svantaggio (non limitato ai punti seguenti: l'elenco potrebbe aumentare)

  • Classi senza costruttori pubblici o protetti non possono essere suddivisi in sottoclasse.
  • Non sono facilmente distinguibili da altri metodi statici.
0

È possibile utilizzare il costruttore privato e pubblico solo nel modo seguente. Ma non puoi usare entrambi per il costruttore di argomenti o lo stesso tipo di argomento.

public class MyClass { 
private MyClass(){ 

} 
public MyClass(int i){ 

} 
} 
0

A giudicare dal codice commentato, l'hai già provato e ha funzionato. Quindi posso solo confermare la tua scoperta: sì, il costruttore privato può coesistere con quello pubblico, e sì, sembra una soluzione migliore poiché viene eseguita più inizializzazione prima di ricevere il riferimento al nuovo oggetto.

Problemi correlati