La méthode finalize, l'interface fermable et l'instruction try-with-resources (Java 7) - 1

« Salut Amigo ! »

"J'ai juste décidé de discuter de la méthode finalize () avec vous."

"Si vous vous en souvenez, finalize() est une méthode spéciale qui est appelée par un objet avant que le ramasse-miettes ne le détruise."

"L'objectif principal de cette méthode est de libérer des ressources externes non Java utilisées en fermant des fichiers, des flux d'E/S, etc."

"Malheureusement, cette méthode ne répond pas à nos attentes. La machine virtuelle Java peut différer la destruction d'un objet, ainsi que l'appel de la méthode finalize, aussi longtemps qu'elle le souhaite. De plus, elle ne garantit pas que cette méthode sera Il y a des tas de situations où il n'est pas appelé, tout cela au nom de "l'optimisation"."

"J'ai deux références pour vous :"

Joshua Bloch a écrit un bon article sur cette méthode : lien
Je vais paraphraser un court extrait :

  1. finalize() ne peut être utilisé que dans deux cas :
    1. Pour vérifier ou nettoyer les ressources avec la journalisation.
    2. Lorsque vous travaillez avec du code natif qui n'est pas critique pour les fuites de ressources.
  2. finalize() rend le GC 430 fois plus lent lors du nettoyage des objets
  3. finalize() peut ne pas être appelé
Si je dis dans une interview que finaliser est une béquille nuisible et dangereuse dont l'existence même prête à confusion, aurais-je raison ?

"Eh bien, ça a fait ma journée, Ellie."

"Java 7 a une nouvelle instruction pour remplacer la méthode finalize . Elle s'appelle try-with-resources . Ce n'est pas vraiment un remplacement pour finalize , c'est plutôt une approche alternative."

"Est-ce que c'est comme essayer-attraper, mais avec des ressources?"

"C'est presque comme try-catch . Contrairement à la méthode finalize () , le bloc finally d'une instruction try- catch-finally est toujours exécuté. Les programmeurs ont également utilisé cette technique lorsqu'ils ont eu besoin de libérer des ressources, fermer les discussions, etc.

"Voici un exemple :"

InputStream is = null;
try
{
 is = new FileInputStream("c:/file.txt");
 is.read(…);
}
finally
{
 if (is != null)
 is.close();
}

"Que le bloc try s'exécute correctement ou qu'il y ait eu une exception, le bloc finally sera toujours appelé et il est possible d'y libérer les ressources occupées."

"Ainsi, dans Java 7, la décision a été prise d'officialiser cette approche, comme ceci :"

try(InputStream is = new FileInputStream("c:/file.txt"))
{
 is.read(…);
}

"Cette instruction try spéciale est appelée try-with-resources (similaire à la façon dont les collections ont une alternative pour appelée foreach )."

"Remarquez qu'après le try, il y a des parenthèses où les variables sont déclarées et les objets sont créés. Ces objets peuvent être utilisés à l'intérieur du bloc try indiqué par les accolades. Lorsque le bloc try est terminé, qu'il se soit terminé normalement ou là était une exception, la méthode close() sera appelée sur tous les objets créés à l'intérieur des parenthèses."

« Comme c'est intéressant ! Cette notation est beaucoup plus compacte que la précédente. Je ne suis pas sûr de l'avoir encore comprise.

"Ce n'est pas aussi difficile que tu le penses."

« Alors, puis-je spécifier la classe de chaque objet entre parenthèses ?

"Oui, bien sûr, sinon les parenthèses ne serviraient à rien."

"Et si j'ai besoin d'appeler une autre méthode après avoir quitté le bloc try, où dois-je la mettre?"

"Les choses sont un peu plus subtiles ici. Java 7 introduit l'interface suivante :"

public interface AutoCloseable
{
 void close() throws Exception;
}

"Votre classe peut implémenter cette interface. Ensuite, vous pouvez utiliser ses objets dans une instruction try-with-resources. Seuls de tels objets peuvent être créés à l'intérieur des parenthèses d'une instruction try-with-resources pour une "fermeture automatique"."

"En d'autres termes, j'ai besoin de remplacer la méthode de fermeture et d'y écrire du code pour "nettoyer" mon objet, et je ne peux pas spécifier une autre méthode ?"

"Oui. Mais vous pouvez spécifier plusieurs objets, séparez-les simplement par un point-virgule :"

try(
InputStream is = new FileInputStream("c:/file.txt");
OutputStream os = new FileOutputStream("c:/output.txt")
)
{
 is.read(…);
 os.write(…);
}

"C'est mieux, mais pas aussi cool que je l'espérais."

"Ce n'est pas si mal. Tu t'y habitueras. Avec le temps."