Newsgroup: it.comp.java
Titolo: Distruttore

Ciao a tutti,
premetto che lavoro con java da parecchi anni, e prima ancora ero un
discreto programmatore C++.
Il passaggio dal C++ a Java è stato entusiasmante e ancora oggi sono un
grande sostenitore dell'ex "Green project".
In tutto questo entusiasmo però, da buon veccio programmatore C++, sento la
mancanza di alcune peculiarità che caratterizzavano tale linguaggio.
Una di queste era la presenza del distruttore, metodo che ritengo
indispensabile quanto il costruttore.
Nel tentativo di poter fruire di un servizio analogo al distruttore ho
cercato di ridefinire il metodo finalize() java.lang.Object ma senza
successo.
Qualcuno mi può aiutare?
Ciao,
CC

 ha scritto nel messaggio
news:bihmv1$37s$1...@lacerta.tiscalinet.it...


 In che contesto ti serve avere un "~distruttore"?
Poniamo che debba essere sicuro che un  mio oggetto java prima di essere
deallocato dal garbag collector chiuda eventuali stream da lui aperti oppure
comunichi ad un server che sta per essere deallocato.
Ovviamente io, chiudere esplicitamente gli stream ma è molto più comodo se
delegassi al mio oggetto questa funzione.
D'altronde il cugino del distruttore: "il costruttore" ha la medesima
funzione, automatizzare alcuni comandi in fase di creazione dell'oggetto.
Ora non capisco perchè in java il concetto di distruttore è stato scartato.
Ciao,
CC

 ha scritto nel messaggio
news:bihtvj$79n$1...@lacerta.tiscalinet.it...


 ha scritto nel messaggio
news:bihtvj$79n$1...@lacerta.tiscalinet.it...


qwerty wrote:

Ciao,
finalize() non è la controparte Java di un distruttore C++.
In C++ i distruttori sono lo strumento naturale per rilasciare risorse(memoria e 
non).
In Java per la memoria, si sa, c'è il GC, e per altre risorse(tipo files, 
threads, connessioni a db ecc.) si usa(o meglio, si può usare) un metodo di 
terminazione esplicita(explicit termination method).
Quando si vuole terminare un oggetto si invoca il suddetto metodo.
È necessario che l'oggetto in questione tenga traccia del proprio 
stato(valido/non valido). In poche parole il metodo di terminazione deve 
registrare in un membro privato dell'oggetto lo stato di quest'ultimo e gli 
altri metodi devono controllare il valore del membro e lanciare una 
IllegalStateException se vengono chiamati dopo aver terminato l'oggetto.
Il metodo close di OutputStream, per esempio, funziona esattamente in questo modo.
Normalmente i metodi di terminazione vengono usati in combinazione con il 
costrutto try-finally
Test test = new Test();
try {
     //usa test..
} finally {
     test.terminate() // Metodo di terminazione esplicita
}
Per sicurezza vale la pena, in caso l'utilizzatore si scordi di utilizzarlo, di 
inserire terminate() anche nel metodo finalize(). Ovviamente questo non ti 
garantisce che terminate() venga eseguito però potrebbre andarti bene.
Marco

Grazie a tutti,
per l'aiuto.
Ciao,
CC

 ti faccio sapere se incontro qualche problema.
Ciao,
no, questo è un errore. Non ci sono garanzie che finalize() venga chiamato  in 
fretta
http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44748
e dunque nessuna operazione time-critical deve essere mai delegata a un 
finalizer(e chiudere connessioni a db, file ecc sono di queste).
Ad esempio dipendere da un finalizer per chiudere un file è rischioso perchè il 
numero di file descriptor che possono essere aperti dal SO sono limitati. Se 
troppi file restano aperti in attesa che il GC faccia pulizia e li chiuda 
potresti ritrovarti nella situazione dove il programma fallisca a causa del 
fatto che non ci sono più file descriptor disponibili...
Inoltre la rapidità con cui i finalizers vengono eseguiti è una funzione del 
algoritmo del GC, che cambia da VM a VM. È possibilissimo che con la VM che usi 
per sviluppare tutto funzioni alla grande ma una volta distribuita 
l'applicazione al tuo cliente(che usa un altra VM e non c'è verso di fargliela 
cambiare :) l'applicazione degradi miseramente... vai poi a fare test e 
debuggare per trovare il problema... ;)
Marco