È una cattiva pratica creare nuovi oggetti senza memorizzarli?


23

Ho visto oggetti creati nel codice Java senza memorizzare un riferimento all'oggetto. Ad esempio, in un plugin eclipse ho visto una shell SWT creata in questo modo:

new Shell();

Questo nuovo oggetto Shell non è memorizzato in una variabile, ma rimarrà referenziato fino a quando non verrà eliminata la finestra che [credo?] Si verifica per impostazione predefinita alla chiusura della finestra.

È una cattiva pratica creare oggetti come questo senza memorizzarne un riferimento? O la biblioteca è stata progettata male? Cosa succede se non ho bisogno di un riferimento, ma voglio solo gli "effetti collaterali" dell'oggetto? Devo comunque memorizzare un riferimento?

AGGIORNARE:

Devo ammettere che il mio esempio sopra è scarso. Mentre ho visto elementi dell'interfaccia utente creati in questo modo, creare una shell SWT come questa sarebbe probabilmente inutile perché è necessario chiamare il metodo open sull'istanza Shell. Ci sono esempi migliori forniti da aix come i seguenti dal tutorial sulla concorrenza Java :

(new HelloThread()).start();

Questa pratica è vista in molti contesti, quindi le domande rimangono. È buona pratica?


2
Quale sarebbe il punto di memorizzazione del riferimento?
Daniel R Hicks,

(Probabilmente sarebbe meglio, da un punto di vista concettuale, avere un metodo statico come Shell.createTopLevelShell()o altro, rispetto all'utilizzo di un costruttore in questo caso. Ma funzionalmente c'è poca differenza.)
Daniel R Hicks

Questa domanda riguarda la pratica di creare oggetti senza fare riferimento a essi, creare classi che richiedono questa pratica o riguarda specificamente il modo in cui SWT utilizza questo tipo di modello?
StriplingWarrior il

1
Gli oggetti SWT devono essere dispose()d: Regola 1: se l'hai creato, lo elimini. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
Vorrei utilizzare una variabile per contenere un riferimento per scopi di debug. Se si dispone di un punto di interruzione in questo metodo, è possibile ottenere il debugger per eseguire query sull'oggetto tramite la variabile locale. Senza il riferimento sono sicuro che sia possibile ma probabilmente molto più difficile.
Martin York,

Risposte:


12

C'è un elemento di preferenza personale in questo, ma penso che non memorizzare il riferimento non sia necessariamente una cattiva pratica.

Considera il seguente esempio ipotetico:

new SingleFileProcessor().process(file);

Se è necessario creare un nuovo oggetto processore per ogni file e non è necessario dopo la process()chiamata, non ha senso memorizzare un riferimento ad esso.

Ecco un altro esempio, tratto dal tutorial sulla concorrenza Java :

(new HelloThread()).start();

Ho visto molti altri esempi quando il riferimento non è stato memorizzato e leggo perfettamente bene ai miei occhi, come:

String str = new StringBuilder().append(x).append(y).append(z).toString();

(L' StringBuilderoggetto non è mantenuto.)

Ci sono modelli simili che coinvolgono common.lang's HashCodeBuilderet al.


2
@BalusC: Con rispetto, non vedo cosa lo rende sospetto e in che modo è meglio avere un metodo factory (suppongo che il tuo esempio sia analogo al mio, ed getInstance()è una factory e non un singleton).
NPE,

Spetta alla fabbrica se usare o meno un singleton. Il chiamante della fabbrica non dovrebbe pensarci troppo.
Donal Fellows,

Nel tuo esempio l'istanza FileProcessor non è (presumibilmente) una volta completata l'istruzione, mentre nell'esempio del PO l'istanza Shell è (sotto le copertine) referenziata da un altro oggetto e quel riferimento (e quindi l'oggetto Shell) persiste oltre durata della dichiarazione.
Daniel R Hicks,

@BalusC: FileProcessor potrebbe avere metodi aggiuntivi per modificare il comportamento di process.
Kevin Cline,

7

Se non hai bisogno di un riferimento all'oggetto creato, non trattenerlo. E 'così semplice.


5

In generale, è buona norma rilasciare riferimenti il ​​più rapidamente possibile. Non vedo alcuna differenza tra:

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

e

(new HelloThread()).start();

Per quanto riguarda il codice, stai semplicemente evitando l'uso di un nome di variabile, che potrebbe essere una cosa positiva. Il compilatore JIT è in genere abbastanza intelligente da riconoscere che può spazzatura raccogliere il thread dopo il suo ultimo utilizzo, quindi probabilmente non c'è differenza dal punto di vista delle prestazioni.

L'unico vero problema da evitare è il codice nell'Anti-Pattern del costruttore , ma non sembra che sia quello che stai chiedendo.


3

Questo potrebbe essere negativo se stai usando SWT, perché lì devi ripulire dopo te stesso (chiamando il metodo dispose ()). Ma per altre classi (non SWT) va bene.

Ecco un articolo sulla gestione delle risorse del sistema operativo


I riferimenti circolari non impediscono che gli oggetti vengano raccolti garbage in Java. Qualsiasi VM Java moderna determina se gli oggetti sono GCable in base al fatto che siano raggiungibili e non utilizza il conteggio dei riferimenti.
jbindel,

2
In effetti non usa il conteggio dei riferimenti. Ma SWT è un caso speciale in cui è necessario chiamare dispose (), anche se non è necessario chiamare prima trattenere ().
Alex,

Volevo riferirmi solo al caso non SWT.
jbindel,

Ecco un articolo sulla gestione delle risorse del sistema operativo eclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
In tal caso, modifica la risposta per rimuovere l'affermazione su "impossibile da GC" in quanto fuorviante.
Donal Fellows,

1

Prima di tutto, infastidirai le persone che hanno imparato C o C ++ prima di Java. Lascio che sia un esercizio per il lettore decidere se è un pro o un contro.

Mentre ci sono certamente situazioni in cui gli oggetti sono progettati per essere di breve durata, il più delle volte se qualcosa è abbastanza complesso per creare un oggetto, è abbastanza complesso da avere buone ragioni per mantenere un riferimento, quindi non tenerlo dovrebbe il minimo è un avvertimento per ricontrollare se hai perso qualcosa.

Ad esempio, in un tutorial nessuno si preoccupa di mantenere un riferimento al thread, ma nella vita reale, se qualcosa impiega abbastanza tempo per generare un thread, di solito ci vuole abbastanza tempo per poter annullare il thread. O se hai una vita più breve, di solito stai generando un sacco di fili che vorrai joinprima di continuare. Oppure vuoi assicurarti che la creazione del tuo thread sia effettivamente riuscita. Oppure vuoi assicurarti che il thread termini in modo pulito prima di uscire. Ottieni l'immagine.


2
Preoccuparsi dei fastidiosi programmatori di altre lingue è davvero la prima preoccupazione?
Buttons840

Lo rende un problema di leggibilità / familiarità / stile a seconda della composizione della tua squadra, perché è uno stile che molte persone portano avanti. Anche le persone che non hanno mai programmato in C ++ spesso adottano stili dai loro mentori che lo hanno fatto.
Karl Bielefeldt,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.