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.
Verifica questo: http://stackoverflow.com/a/11360712/1544069 – ritesh
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
Certo, mi scuso. Terrò in nota e ringrazio tutta la comunità per l'aiuto, anche grazie per averlo segnalato alla mia attenzione. – JavaDeveloper