627 votes

Y a-t-il un destructeur pour Java ?

Est-il destructeur pour Java? Je ne semble pas être en mesure de trouver toute la documentation sur ce sujet. Si il n'y en a pas, comment puis-je obtenir le même effet?

Pour faire à ma question plus spécifique, je suis en train d'écrire une application qui traite les données, et la spécification de dire qu'il devrait y avoir un bouton "réinitialiser" qui apporte de l'application à son origine vient de lancer état. Cependant, toutes les données doivent être "live", sauf si l'application est fermée ou réinitialiser le bouton est pressé.

Étant habituellement un C/C++ programmeur, je pensais que ce serait facile à implémenter. (Et j'ai donc prévu de mettre en œuvre ce dernier.) J'ai structuré mon programme tel que le "reset" en mesure les objets sont dans une même classe, ce que je peux juste détruire tous les "en direct" des objets lorsque le bouton est pressé.

Je pensais, si j'ai tout juste à déréférencer les données et d'attendre que le garbage collector pour les recueillir, ne serait-il pas être une fuite de mémoire si mon utilisateur à plusieurs reprises les données entrées et appuyé sur le bouton de réinitialisation? Je me disais aussi, depuis Java est assez mature comme un langage, il devrait y avoir un moyen d'empêcher que cela se produise ou gracieusement remédier.

557voto

Garth Gilmour Points 5219

Parce que Java est un de ces ordures de la langue vous ne pouvez pas prédire quand (ou si) d'un objet sera détruit. Donc il n'y a pas d'équivalent direct d'un destructeur.

Il y a une méthode héritée appelé à finaliser, mais ceci est appelé entièrement à la discrétion du garbage collector. Donc, pour les classes qui doivent explicitement ranger, la convention est de définir un proche de la méthode et de l'utilisation de finaliser seulement pour la santé mentale de contrôle (c'est à dire si proche n'a pas été appelé à le faire maintenant et journal d'une erreur).

Il y a une question qui a engendré une discussion en profondeur de finaliser récemment, ce qui devrait donner plus de profondeur si nécessaire...

136voto

Vitalii Fedorenko Points 17469

Si vous utilisez Java 7, avoir un regard sur le try-with-resources déclaration. Par exemple:

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

Ici, la ressource n'est plus nécessaire est libérée dans l' BufferedReader.close() méthode. Vous pouvez créer votre propre classe qui implémente les Fermer et de les utiliser dans un mode similaire.

Cette déclaration est plus limitée que finalize en termes de code de la structuration, mais en même temps, elle rend le code plus simple à comprendre et à maintenir. Aussi, il n'y a pas de garantie qu'un finalize méthode est appelée lors de la livetime de l'application.

112voto

ddimitrov Points 2005

Nope, pas de destructeurs ici. La raison en est que tous les objets Java sont des tas alloués et les ordures collectées. Sans l'accord de libération de la mémoire (c'est à dire C++opérateur delete) il n'y a pas de meilleure façon de mettre en œuvre de véritables destructeurs.

Java prend en charge les finaliseurs, mais ils sont conçus pour être utilisés seulement comme une clause de sauvegarde pour des objets ayant une poignée de ressources autochtones comme les prises, les descripteurs de fichiers, poignées de fenêtre, etc. Lorsque le garbage collector recueille un objet sans un finaliseur il marque simplement la zone de mémoire libre et c'est tout. Lorsque l'objet a un finaliseur, c'est d'abord copié dans un emplacement temporaire, (rappelez-vous, nous sommes à la collecte des ordures ici), puis il est mis en file d'attente en attente d'être finalisé file d'attente, puis un Finaliseur fil des sondages de la file d'attente avec priorité très basse et exécute l'outil de finalisation.

Tous les Finaliseurs sont exécutés dans le même thread, donc si l'un des finaliseurs se bloque, tout le finaliseur thread se bloque. Si vous jeter une exception, cela peut tuer le thread finaliseur (bien que la JVM est libre de respawn un nouveau) et dans le pire des cas, aucune autre objets en cours sera achevée. Lorsque l'application se ferme, la machine s'arrête sans attente pour les objets en cours d'être finalisé, donc il n'y a pratiquement aucune garantie que votre finaliseurs sera jamais exécuté.

31voto

McDowell Points 62645

L'utilisation de finalize() méthodes doit être évitée. Ils ne sont pas un mécanisme fiable de ressources nettoyer et il est possible de provoquer des problèmes dans le garbage collector en abuser.

Si vous avez besoin d'une libération de l'appel dans votre objet, dire à libérer des ressources, l'utilisation explicite de l'appel de méthode. La présente convention peut être vu dans les APIs existantes (par exemple, Fermer, Graphiques.dispose(), Widget.dispose()) et est généralement appelé via le try/finally.

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

Les tentatives d'utilisation d'un objet supprimé doit lancer une exception d'exécution (voir l'exception IllegalStateException).


EDIT:

Je pensais, si j'ai tout juste déréférencer les données et d'attendre le garbage collector pour les ramasser, ne serait-il pas être une fuite de mémoire si mon l'utilisateur à plusieurs reprises les données entrées et les appuyé sur le bouton de réinitialisation?

En général, tout ce que vous devez faire est de déréférencer les objets - au moins, ce est la façon dont il est censé fonctionner. Si vous êtes inquiet au sujet de la collecte des ordures, découvrez Java SE 6 HotSpot[tm] de la Machine Virtuelle de Collecte des Ordures Tuning (ou le document équivalent pour votre version de la JVM).

23voto

waku Points 61

Avec Java 1.7 libéré, vous avez maintenant la possibilité supplémentaire d’utiliser le bloc try-with-resources. Par exemple,

Si vous exécutez cette classe, c.close() sera exécuté lorsque le bloc try est à gauche et avant la prise et enfin les blocs sont exécutés. Contrairement à dans le cas de la méthode finalize(), close() est garanti d’être exécuté. Cependant, il n’y a pas besoin de l’exécuter explicitement dans la clause finally.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X