Esiste un distruttore per Java?


594

Esiste un distruttore per Java? Non riesco a trovare alcuna documentazione al riguardo. In caso contrario, come posso ottenere lo stesso effetto?

Per rendere la mia domanda più specifica, sto scrivendo un'applicazione che si occupa di dati e le specifiche dicono che dovrebbe esserci un pulsante 'reset' che riporta l'applicazione al suo stato originale appena lanciato. Tuttavia, tutti i dati devono essere "attivi" a meno che l'applicazione non venga chiusa o non venga premuto il pulsante di ripristino.

Essendo di solito un programmatore C / C ++, ho pensato che sarebbe stato banale implementarlo. (E quindi ho pianificato di implementarlo per ultimo.) Ho strutturato il mio programma in modo tale che tutti gli oggetti "ripristinabili" fossero nella stessa classe in modo da poter semplicemente distruggere tutti gli oggetti "live" quando viene premuto un pulsante di ripristino.

Stavo pensando se tutto ciò che facevo fosse solo quello di dereferenziare i dati e aspettare che il garbage collector li raccogliesse, non ci sarebbe una perdita di memoria se il mio utente immettesse ripetutamente i dati e premesse il pulsante di ripristino? Stavo pensando anche perché Java è abbastanza maturo come linguaggio, dovrebbe esserci un modo per impedire che ciò accada o affrontarlo con grazia.


7
C'è solo una perdita di memoria se si mantengono riferimenti a oggetti non necessari. cioè c'è un bug nel tuo programma. Il GC funzionerà come necessario (a volte prima)
Peter Lawrey,

17
La macchina virtuale non eseguirà GC abbastanza presto se si elaborano rapidamente dati attraverso oggetti. L'idea che il GC possa sempre tenere il passo o prendere le giuste decisioni è un errore.
Kieveli,

1
@Kieveli JVM non avrebbe eseguito GC prima di dare un errore?
WVrock,

4
Sì, sarebbe bello se ci fosse un distruttore per Java che lo distruggerebbe una volta per tutte.
Tomáš Zato - Ripristina Monica

Risposte:


526

Poiché Java è un linguaggio garbage collection, non è possibile prevedere quando (o anche se) un oggetto verrà distrutto. Quindi non esiste un equivalente diretto di un distruttore.

Esiste un metodo ereditato chiamato finalize, ma questo viene chiamato interamente a discrezione del Garbage Collector. Quindi, per le classi che hanno bisogno di riordinare esplicitamente, la convenzione è di definire un metodo di chiusura e usare finalizza solo per il controllo di integrità (cioè se non è stato chiamato chiusura, fallo ora e registra un errore).

C'è stata una domanda che ha generato una discussione approfondita sulla finalizzazione di recente, quindi dovrebbe fornire maggiore profondità se necessario ...


5
"Close ()" in questo contesto fa riferimento al metodo in java.lang.Autocloseable?
Sridhar Sarnobat,

21
No, AutoCloseable è stato introdotto in Java 7 ma la convenzione 'close ()' è in circolazione da molto più tempo.
Jon Onstott,

perché non puoi prevedere quando (o anche se) un oggetto verrà distrutto. quale altro modo approssimativo per prevederlo?
dctremblay,

La distruzione degli oggetti @dctremblay viene eseguita da Garbage Collector e Garbage Collector potrebbe non essere mai in esecuzione per tutta la durata dell'applicazione.
Piro dice di reintegrare Monica il

4
Si noti che il finalizemetodo è stato deprecato in Java 9.
Lii

124

Dai un'occhiata all'istruzione try-with-resources . Per esempio:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

Qui la risorsa non più necessaria viene liberata nel BufferedReader.close()metodo. Puoi creare la tua classe che implementa AutoCloseablee usarla in modo simile.

Questa affermazione è più limitata che finalizein termini di strutturazione del codice, ma allo stesso tempo semplifica la comprensione e la manutenzione del codice. Inoltre, non vi è alcuna garanzia che un finalizemetodo venga chiamato durante il live-time dell'applicazione.


12
Sono sorpreso che questo abbia così pochi voti. È la risposta effettiva.
Nurettin,

20
Non sono d'accordo che sia la risposta effettiva. Se un'istanza ha una risorsa che gestisce per un periodo di tempo più ampio, attraverso più chiamate di metodo, provare con le risorse non sarà di aiuto. A meno che non sia corretto chiudere e riaprire detta risorsa al ritmo a cui vengono chiamati i metodi - non è un fatto generale.
Eric,

14
In effetti, questa non è la risposta effettiva. È impossibile utilizzare questa struttura per gestire la distruzione di un oggetto a meno che la costruzione e l'uso dell'oggetto non siano interamente incapsulati da trye finallyvenga utilizzato per forzare una chiamata a obj.finalize(). E anche questa configurazione non risolve il problema posto dall'OP: programma intermedio di distruzione degli oggetti attivato da un pulsante "reset".
7yl4r,

1
Altri utenti hanno dimostrato che ciò viene fatto nel punto di ingresso dell'applicazione. Definisci la tua variabile a livello globale. Inizializzalo nella funzione di inserimento, con try. Disinizializza finalmente (alla chiusura dell'applicazione). È del tutto possibile.
TamusJRoyce,

1
@nurettin Java 7 era uscito solo da 3 mesi quando è stata posta la domanda, se ciò ha più senso.
corsiKa

110

No, nessun distruttore qui. Il motivo è che tutti gli oggetti Java sono allocati in heap e garbage collection. Senza esplicita deallocazione (cioè l'operatore di eliminazione di C ++) non esiste un modo ragionevole per implementare i veri distruttori.

Java supporta i finalizzatori, ma sono pensati per essere utilizzati solo come protezione per oggetti che trattengono un handle di risorse native come socket, handle di file, handle di finestre, ecc. Quando il Garbage Collector raccoglie un oggetto senza un finalizzatore, contrassegna semplicemente la memoria regione libera e basta. Quando l'oggetto ha un finalizzatore, viene prima copiato in una posizione temporanea (ricordate, stiamo raccogliendo la spazzatura qui), quindi viene accodato in una coda in attesa di essere finalizzata e quindi un thread Finalizer esegue il polling della coda con priorità molto bassa ed esegue il finalizzatore.

Quando l'applicazione viene chiusa, JVM si arresta senza attendere la finalizzazione degli oggetti in sospeso, quindi praticamente non esiste alcuna garanzia che i finalizzatori vengano mai eseguiti.


4
Grazie per aver menzionato le risorse native: questa è un'area in cui è utile un metodo "simile a un distruttore".
Nathan Osman

sì, sto affrontando lo stesso problema in questo momento con la liberazione di risorse / handle allocati tramite chiamate native a C ++.
Nikk

@ddimitrov, in teoria Java potrebbe implementare la deallocazione esplicita? O è una contraddizione logica?
mil

1
@mils implementando ingenuamente la deallocazione esplicita interromperebbe il presupposto Java che qualsiasi riferimento rimanda a un oggetto live. Puoi iterare su tutti i puntatori e annullare gli alias, ma è più costoso di GC. Oppure puoi provare ad usare un sistema di tipo lineare (vedi "proprietà" in Rust), ma questo è un cambiamento di lingua importante. Esistono anche altre opzioni (vedi memoria con ambito JavaRT, ecc.), Ma in generale la deallocazione esplicita non si adatta bene al linguaggio Java.
ddimitrov,

31

L'uso dei metodi finalize () dovrebbe essere evitato. Non sono un meccanismo affidabile per la pulizia delle risorse ed è possibile causare problemi nel garbage collector abusandoli.

Se è necessaria una chiamata di deallocazione nell'oggetto, dire di rilasciare risorse, utilizzare una chiamata di metodo esplicita. Questa convenzione può essere vista nelle API esistenti (ad es. Closeable , Graphics.dispose () , Widget.dispose () ) e di solito viene chiamata tramite try / finally.

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

I tentativi di utilizzare un oggetto eliminato dovrebbero generare un'eccezione di runtime (consultare IllegalStateException ).


MODIFICARE:

Stavo pensando, se tutto ciò che facevo fosse solo quello di dereferenziare i dati e aspettare che il garbage collector li raccogliesse, non ci sarebbe una perdita di memoria se il mio utente immettesse ripetutamente i dati e premesse il pulsante di ripristino?

Generalmente, tutto ciò che devi fare è dereferenziare gli oggetti - almeno, questo è il modo in cui dovrebbe funzionare. Se sei preoccupato per la garbage collection, dai un'occhiata a Java SE 6 HotSpot [tm] Virtual Machine Garbage Collection Tuning (o al documento equivalente per la tua versione JVM).


1
Non è questo che significa dereference. Non si tratta di "impostare l'ultimo riferimento di un oggetto su null", ma piuttosto di ottenere (leggere) il valore da un riferimento in modo da poterlo utilizzare per le operazioni successive.

1
Try..finally è ancora un approccio valido e raccomandato? Supponiamo che in precedenza stavo chiamando un metodo nativo in finalize (), posso spostare la chiamata nella clausola finally? class Resource { finalize() { destroy(); } protected native void destroy(); } class Alt_Resource { try (Resource r = new Resource()) { // use r } finalize { r.destroy(); }
aashima,

r non verrebbe inserito nel blocco finally. Pertanto, non è possibile chiamare distruggere a quel punto. Ora, se si corregge l'ambito per avere la creazione dell'oggetto prima del blocco try, si finirebbe con il brutto caso "prima di provare con le risorse".
userAsh

21

Con Java 1.7 rilasciato, ora hai l'opzione aggiuntiva di usare il try-with-resourcesblocco. Per esempio,

public class Closeable implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("closing..."); 
    }
    public static void main(String[] args) {
        try (Closeable c = new Closeable()) {
            System.out.println("trying..."); 
            throw new Exception("throwing..."); 
        }
        catch (Exception e) {
            System.out.println("catching..."); 
        }
        finally {
            System.out.println("finalizing..."); 
        } 
    }
}

Se esegui questa classe, c.close()verrà eseguito quandotry blocco viene lasciato e prima catchche finallyvengano eseguiti i blocchi e . Diversamente dal caso del finalize()metodo, close()è garantito l'esecuzione. Tuttavia, non è necessario eseguirlo esplicitamente nella finallyclausola.


e se non avessimo usato il blocco try-with-resources? Penso che possiamo chiamare close in finalize () solo per assicurarci che close sia stato chiamato.
shintoZ,

3
@shintoZ, come ho letto nelle risposte precedenti, non esiste alcuna garanzia di finalize()esecuzione
Asif Mushtaq,

14

Concordo pienamente con altre risposte, dicendo di non fare affidamento sull'esecuzione di finalizza.

Oltre ai blocchi try-catch-finally, è possibile utilizzare Runtime # addShutdownHook (introdotto in Java 1.3) per eseguire le pulizie finali del programma.

Non è lo stesso dei distruttori , ma è possibile implementare un hook di arresto con oggetti listener registrati su cui è possibile invocare metodi di pulizia (chiudere connessioni al database persistenti, rimuovere blocchi di file e così via) - cose che normalmente si farebbero in distruttori . Ancora una volta - questo non è un sostituto per i distruttori ma in alcuni casi, è possibile avvicinarsi alla funzionalità desiderata con questo.

Il vantaggio è che il comportamento di decostruzione è vagamente accoppiato al resto del programma.


addShutdownHook è stato apparentemente introdotto in Java 1.3. Comunque, è disponibile per me in 1.5. :) Vedi questo: stackoverflow.com/questions/727151/...
skiphoppy

1
Cordiali saluti, nella mia esperienza non verranno chiamati hook di arresto se si utilizza il pulsante rosso "termina" in Eclipse: l'intera JVM viene immediatamente distrutta, gli hook di arresto non vengono chiamati con grazia. Ciò significa che potresti vedere comportamenti diversi durante lo sviluppo e la produzione se sviluppi utilizzando eclissi
Hamy,

11

No, java.lang.Object#finalize è il più vicino che puoi ottenere.

Tuttavia, quando (e se) viene chiamato, non è garantito.
Vedere:java.lang.Runtime#runFinalizersOnExit(boolean)


5
Un metodo che può o non può essere chiamato è essenzialmente inutile nel mio libro. Sarebbe stato meglio non inquinare la lingua con un metodo speciale inutile che nella migliore delle ipotesi dà un falso senso di sicurezza. Non capirò mai perché gli sviluppatori del linguaggio Java abbiano pensato che finalizzare fosse una buona idea.
Antred,

@antred Gli sviluppatori del linguaggio Java sono d'accordo . Immagino, allora, per alcuni di loro, era la prima volta che progettavano un linguaggio di programmazione e un ambiente di runtime con Garbage Collection. Ciò che è meno comprensibile, è il motivo per cui quell'altro linguaggio gestito ha copiato quel concetto alla volta, quando si era già capito che questo concetto è una cattiva idea.
Holger,

7

Innanzitutto, si noti che poiché Java è stato raccolto in modo inutile, è raro dover fare qualcosa per la distruzione degli oggetti. In primo luogo perché di solito non hai risorse gestite da liberare, e in secondo luogo perché non puoi prevedere quando o se accadrà, quindi è inappropriato per le cose che devono accadere "non appena nessuno sta più usando il mio oggetto ".

Puoi essere avvisato dopo che un oggetto è stato distrutto usando java.lang.ref.PhantomReference (in realtà, dire che è stato distrutto potrebbe essere leggermente impreciso, ma se un riferimento fantasma ad esso viene messo in coda, non sarà più recuperabile, che di solito equivale a la stessa cosa). Un uso comune è:

  • Separa le risorse della tua classe che devono essere distrutte in un altro oggetto helper (nota che se tutto ciò che stai facendo è chiudere una connessione, che è un caso comune, non è necessario scrivere una nuova classe: la connessione da chiudere sarebbe in tal caso l '"oggetto helper").
  • Quando crei il tuo oggetto principale, crea anche un PhantomReference. Fare in modo che si riferiscano al nuovo oggetto helper o impostare una mappa dagli oggetti PhantomReference ai loro oggetti helper corrispondenti.
  • Dopo che l'oggetto principale è stato raccolto, PhantomReference viene messo in coda (o meglio, può essere messo in coda - come per i finalizzatori, non vi è alcuna garanzia che lo sarà mai, ad esempio se la VM esce e non attende). Assicurati di elaborarne la coda (in un thread speciale o di volta in volta). A causa del duro riferimento all'oggetto helper, l'oggetto helper non è stato ancora raccolto. Quindi esegui qualsiasi operazione di pulizia sull'oggetto helper, quindi scarta PhantomReference e alla fine anche l'helper verrà raccolto.

C'è anche finalize (), che sembra un distruttore ma non si comporta come tale. Di solito non è una buona opzione.


Perché un PhantomReference invece di un WeakReference?
Uckelman,

2
@uckelman: se tutto ciò che vuoi è una notifica, allora PhantomReference fa il lavoro, questo è praticamente quello per cui è stato progettato. La semantica aggiuntiva di WeakReference non è necessaria qui, e nel punto in cui viene notificato ReferenceQueue, non è più possibile recuperare l'oggetto tramite WeakReference, quindi l'unico motivo per utilizzarlo è salvare dover ricordare che PhantomReference esiste. Qualsiasi lavoro extra che fa WeakReference è probabilmente trascurabile, ma perché preoccuparsene?
Steve Jessop,

Grazie per il suggerimento su PhantomReference. Non è perfetto, ma è ancora meglio di niente.
Foo

@SteveJessop quale "lavoro extra", pensi, ha un riferimento debole rispetto a un riferimento fantasma?
Holger,

6

La finalize()funzione è il distruttore.

Tuttavia, non dovrebbe essere normalmente utilizzato perché viene invocato dopo il GC e non si può dire quando ciò accadrà (se mai).

Inoltre, ci vuole più di un GC per deallocare oggetti che hanno finalize().

Dovresti provare a ripulire nei punti logici del tuo codice usando le try{...} finally{...}istruzioni!


5

Sono d'accordo con la maggior parte delle risposte.

Non dovresti dipendere completamente da finalizeoShutdownHook

Finalizza

  1. La JVM non garantisce quando finalize()verrà invocato questo metodo.

  2. finalize()viene chiamato solo una volta dal thread GC. Se un oggetto si ripristina dal metodo di finalizzazione, finalizenon verrà più richiamato.

  3. Nella tua applicazione, potresti avere alcuni oggetti live, sui quali non viene mai richiamata la garbage collection.

  4. Tutto Exceptionciò che viene lanciato dal metodo di finalizzazione viene ignorato dal thread GC

  5. System.runFinalization(true)e i Runtime.getRuntime().runFinalization(true)metodi aumentano la probabilità di invocare il finalize()metodo, ma ora questi due metodi sono stati deprecati. Questi metodi sono molto pericolosi a causa della mancanza di sicurezza del thread e della possibile creazione di deadlock.

shutdownHooks

public void addShutdownHook(Thread hook)

Registra un nuovo hook di spegnimento della macchina virtuale.

La macchina virtuale Java si spegne in risposta a due tipi di eventi:

  1. Il programma termina normalmente quando esce l'ultimo thread non daemon o quando esce (equivalentemente, System.exit viene invocato il metodo ) oppure
  2. La macchina virtuale viene terminata in risposta a un interrupt utente, come digitare ^ C, o un evento a livello di sistema, come la disconnessione dell'utente o l'arresto del sistema.
  3. Un hook di arresto è semplicemente un thread inizializzato ma non avviato. Quando la macchina virtuale inizia la sequenza di arresto, avvia tutti gli hook di arresto registrati in un ordine non specificato e li lascia funzionare contemporaneamente. Al termine di tutti gli hook, verranno eseguiti tutti i finalizzatori non invocati se la finalizzazione all'uscita è stata abilitata.
  4. Alla fine, la macchina virtuale si arresterà. Si noti che i thread daemon continueranno a essere eseguiti durante la sequenza di arresto, così come i thread non daemon se l'arresto è stato avviato invocando il metodo exit.
  5. Anche i ganci di arresto dovrebbero finire rapidamente il loro lavoro. Quando un programma richiama exit, l'aspettativa è che la macchina virtuale si spenga e si spenga rapidamente.

    Ma anche la documentazione di Oracle lo citava

In rare circostanze, la macchina virtuale potrebbe interrompersi, ovvero interrompere l'esecuzione senza spegnersi in modo pulito

Ciò si verifica quando la macchina virtuale viene terminata esternamente, ad esempio con il SIGKILLsegnale su Unix o la TerminateProcesschiamata su Microsoft Windows. La macchina virtuale può anche interrompere se un metodo nativo non funziona, ad esempio corrompendo le strutture di dati interni o tentando di accedere alla memoria inesistente. Se la macchina virtuale si interrompe, non è possibile fornire alcuna garanzia sull'esecuzione o meno di hook di arresto.

Conclusione : utilizzare i try{} catch{} finally{}blocchi in modo appropriato e rilasciare le risorse critiche in finally(}blocco. Durante il rilascio di risorse in finally{}blocco, cattura Exceptione Throwable.


4

Se è solo la memoria di cui sei preoccupato, non farlo. Fidati del GC che fa un lavoro decente. In realtà ho visto qualcosa che era così efficiente che potrebbe essere meglio per le prestazioni creare cumuli di piccoli oggetti piuttosto che utilizzare grandi array in alcuni casi.


3

Forse puoi usare un blocco try ... finally per finalizzare l'oggetto nel flusso di controllo in cui stai utilizzando l'oggetto. Ovviamente non succede automaticamente, ma nemmeno la distruzione in C ++. Spesso vedi la chiusura delle risorse nel blocco finally.


1
Questa è la risposta giusta quando la risorsa in questione ha un solo proprietario e non ha mai riferimenti ad essa "rubati" da altri codici.
Steve Jessop,

3

C'è un'annotazione @Cleanup in Lombok che assomiglia principalmente ai distruttori C ++:

@Cleanup
ResourceClass resource = new ResourceClass();

Durante l'elaborazione (al momento della compilazione), Lombok inserisce il try-finallyblocco appropriato in modo che resource.close()venga invocato, quando l'esecuzione lascia l'ambito della variabile. Puoi anche specificare esplicitamente un altro metodo per rilasciare la risorsa, ad esempio resource.dispose():

@Cleanup("dispose")
ResourceClass resource = new ResourceClass();

2
Il vantaggio che vedo è che ci sarà meno nidificazione (il che può essere significativo se si hanno molti oggetti che richiedono "distruzione").
Alexey,

Un blocco try-with-resource può avere più risorse in un colpo solo
Alexander: ripristina Monica il

1
Ma non può avere istruzioni tra di loro.
Alexey,

Giusto. Suppongo quindi che la raccomandazione sia quella di preferire try-with-resource, anche per più risorse, a meno che non ci sia bisogno di istruzioni tra loro che ti costringano a creare nuovi blocchi try-with-resource (crescente annidamento), quindi utilizzare@Cleanup
Alexander - Reinstate Monica,

2

L'equivalente più vicino a un distruttore in Java è il metodo finalize () . La grande differenza rispetto a un distruttore tradizionale è che non puoi essere sicuro di quando verrà chiamato, poiché questa è la responsabilità del garbage collector. Consiglio vivamente di leggere attentamente questo prima di usarlo, poiché i tuoi tipici schemi RAIA per gli handle di file e così via non funzioneranno in modo affidabile con finalize ().


2

Molte ottime risposte qui, ma ci sono alcune informazioni aggiuntive sul perché dovresti evitare di usare finalize () .

Se la JVM termina a causa di System.exit()o Runtime.getRuntime().exit(), i finalizzatori non verranno eseguiti per impostazione predefinita. Da Javadoc per Runtime.exit () :

La sequenza di arresto della macchina virtuale è composta da due fasi. Nella prima fase tutti gli hook di arresto registrati, se presenti, vengono avviati in un ordine non specificato e possono essere eseguiti contemporaneamente fino al termine. Nella seconda fase vengono eseguiti tutti i finalizzatori non invocati se la finalizzazione all'uscita è stata abilitata. Fatto ciò, la macchina virtuale si arresta.

Puoi chiamare System.runFinalization() ma fa solo "uno sforzo migliore per completare tutte le finalizzazioni in sospeso", non una garanzia.

C'è un System.runFinalizersOnExit()metodo, ma non usarlo: è pericoloso, deprecato molto tempo fa.


1

Se stai scrivendo un'applet Java, puoi sovrascrivere il metodo "destroy ()" dell'applet. È...

 * Called by the browser or applet viewer to inform
 * this applet that it is being reclaimed and that it should destroy
 * any resources that it has allocated. The stop() method
 * will always be called before destroy().

Ovviamente non è quello che vuoi, ma potrebbe essere quello che cercano gli altri.


1

Basti pensare alla domanda originale ... che, penso, possiamo concludere da tutte le altre risposte apprese, e anche dall'efficace Java essenziale di Bloch , punto 7, "Evita i finalizzatori", cerca la soluzione a una domanda legittima in un modo che è inappropriato per il linguaggio Java ...:

... non sarebbe una soluzione abbastanza ovvia fare ciò che l'OP vuole effettivamente essere per mantenere tutti i tuoi oggetti che devono essere ripristinati in una sorta di "box", a cui tutti gli altri oggetti non ripristinabili hanno riferimenti solo attraverso una sorta dell'oggetto accessorio ...

E poi, quando è necessario "resettare", si disconnette il box esistente e ne si crea uno nuovo: tutta la rete di oggetti nel box viene lanciata alla deriva, per non tornare mai più e un giorno per essere raccolta dal GC.

Se uno di questi oggetti è Closeable(o no, ma ha un closemetodo), puoi metterli nel Bagbox mentre vengono creati (e possibilmente aperti), e l'ultimo atto dell'accessorio prima di tagliare il box sarebbe quello di andare attraverso tutto ilCloseables chiusure ...?

Il codice sarebbe probabilmente simile a questo:

accessor.getPlaypen().closeCloseables();
accessor.setPlaypen( new Playpen() );

closeCloseablessarebbe probabilmente un metodo di blocco, che probabilmente implica un latch (ad es. CountdownLatch), per gestire (e attendere come appropriato) qualsiasi Runnables/ Callablesin qualsiasi thread specifico Playpenper essere terminato come appropriato, in particolare nel thread JavaFX.


0

Sebbene ci siano stati notevoli progressi nella tecnologia GC di Java, devi comunque essere consapevole dei tuoi riferimenti. Vengono in mente numerosi casi di schemi di riferimento apparentemente banali che sono in realtà nidi di ratti sotto il cappuccio.

Dal tuo post non sembra che tu stia provando a implementare un metodo di ripristino ai fini del riutilizzo degli oggetti (vero?). I tuoi oggetti contengono altri tipi di risorse che devono essere ripuliti (ovvero flussi che devono essere chiusi, oggetti in pool o presi in prestito che devono essere restituiti)? Se l'unica cosa di cui ti preoccupi è il dealloc della memoria, riconsidererei la mia struttura di oggetti e proverei a verificare che i miei oggetti siano strutture autonome che verranno ripulite al momento del GC.



0

Nessun Java non ha alcun distruttore. La ragione principale dietro di esso in Java è il Garbage Collector che lavora sempre passivamente in background e tutti gli oggetti sono fatti nella memoria dell'heap, che è il luogo in cui lavora GC. In c ++ ci deve chiamare esplicitamente la funzione di eliminazione poiché non esiste un Garbage Collector.


-3

Mi occupavo principalmente di C ++ e questo è ciò che mi ha portato anche alla ricerca di un distruttore. Sto usando molto JAVA ora. Quello che ho fatto, e potrebbe non essere il caso migliore per tutti, ma ho implementato il mio distruttore ripristinando tutti i valori su 0 o lì di default tramite una funzione.

Esempio:

public myDestructor() {

variableA = 0; //INT
variableB = 0.0; //DOUBLE & FLOAT
variableC = "NO NAME ENTERED"; //TEXT & STRING
variableD = false; //BOOL

}

Idealmente, questo non funzionerà per tutte le situazioni, ma dove ci sono variabili globali funzionerà finché non ne avrai una tonnellata.

So di non essere il miglior programmatore Java, ma sembra funzionare per me.


Cerca di usare più oggetti immutabili, dopo averlo "capito" avrà più senso :)
R. van Twisk,

5
Questo non è tanto sbagliato in quanto è inutile - cioè non raggiunge nulla. Se il tuo programma richiede che i tipi non elaborati vengano reimpostati per funzionare correttamente, le istanze delle tue classi hanno un ambito errato, il che significa che probabilmente stai riassegnando le proprietà di un oggetto esistente alle proprietà di un nuovo oggetto, senza creare un nuovo Object ().
simo.3792

1
Tranne che ci sono molte esigenze per ripristinare le variabili. Ho scelto il nome distruttore perché si adatta a quello che sto facendo. Raggiunge qualcosa, proprio niente che tu capisca
ChristianGLong,
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.