394 votes

Pourquoi voudriez-vous mettre en place finalize ()?

J'ai lu beaucoup de choses de la recrue Java questions sur finalize() et de trouver ça incroyable que personne n'a vraiment fait de la plaine, finalize() est peu fiable façon de nettoyer les ressources. J'ai vu quelqu'un de commentaires qu'ils utilisent pour nettoyer les Connexions, ce qui est vraiment effrayant, puisque la seule façon de se rapprocher de la garantie qu'une Connexion est fermée est de mettre en œuvre essayer (catch) enfin.

Je n'ai pas été éduqué dans CS, mais j'ai été la programmation en Java professionnellement depuis près d'une décennie maintenant, et je n'ai jamais vu personne mettre en œuvre finalize() dans un système de production jamais. Ce n'est pas pour autant qu'il n'a pas ses usages, ou que les gens avec qui j'ai travaillé ont été en train de faire.

Donc ma question est, ce que les cas d'utilisation sont là pour la mise en œuvre de finalize() ne peuvent pas être traitées de manière plus fiable, en passant par un autre processus ou de syntaxe dans la langue?

Veuillez fourni des scénarios spécifiques ou de votre expérience, il suffit de répéter un Java livre de texte, ou de finaliser l'usage prévu n'est pas suffisant, et n'est pas le but de cette question.

244voto

John M Points 6468

Vous pouvez l'utiliser comme un filet de sécurité pour un objet la tenue d'une ressource externe (socket, fichier, etc). Mettre en œuvre une méthode close() et document qu'il doit être appelé.

Mettre en œuvre finalize() pour faire le close() de traitement si vous remarquez qu'il n'a pas été fait. Peut-être avec quelque chose d'un dumping sur la sortie stderr au point que vous êtes le nettoyage après un buggy de l'appelant.

Il offre plus de sécurité dans une exceptionnelle/buggy situation. Pas tous les appelant va faire le bon try {} finally {} trucs à chaque fois. Malheureux, mais vrai dans la plupart des environnements.

Je suis d'accord qu'il est rarement nécessaire. Et comme les commentateurs le soulignent, il est livré avec GC frais généraux. A utiliser uniquement si vous avez besoin de cette "ceinture et bretelles" de la sécurité dans une application en cours d'exécution.

186voto

Steve Jessop Points 166970

finalize() est une allusion à la JVM qu'il pourrait être sympa pour l'exécution de votre code à un temps indéterminé. C'est bon lorsque vous souhaitez code mystérieusement de ne pas s'exécuter.

Faire quelque chose de significatif dans les finaliseurs (fondamentalement rien à l'exception de l'exploitation forestière) est aussi bon dans trois situations:

  • vous voulez jouer que d'autres finalisé objets seront toujours dans un état que le reste de votre programme de juge valable.
  • vous souhaitez ajouter beaucoup de code de vérification pour toutes les méthodes de toutes les classes qui ont un finaliseur, assurez-vous qu'ils se comportent correctement après la finalisation.
  • vous souhaitez accidentellement ressusciter finalisé objets, et de passer beaucoup de temps à essayer de comprendre pourquoi ils ne travaillent pas, et/ou pourquoi ils n'obtiennent pas finalisé quand ils sont finalement relâchés.

Si vous pensez que vous avez besoin finalize(), parfois, ce que vous voulez vraiment est un fantôme de référence (qui dans l'exemple donné pourrait tenir une dur de référence pour une connexion utilisé par son referand et de la fermer après le fantôme de référence a été mis en file d'attente). Cela a aussi la propriété de ce qu'il peut, mystérieusement, ne jamais courir, mais au moins, il ne peut pas appeler des méthodes sur ou ressusciter finalisé objets. Donc c'est juste pour les situations où vous n'avez pas absolument besoin de fermer la connexion proprement, mais vous aimerais, et les clients de votre classe ne peut pas ou ne veut pas l'appeler sur elles-mêmes (qui est en fait juste assez - ce qui est le point d'avoir un garbage collector à tous si vous concevez des interfaces qui nécessitent une action spécifique de l'être prises avant la collecte? Qui vient nous met dans les jours de malloc/free.)

D'autres fois, vous avez besoin de la ressource que vous pensez que vous êtes à la gestion à être plus robuste. Par exemple, pourquoi avez-vous besoin pour fermer la connexion? Elle doit être basée sur une sorte d'e/S fournis par le système (socket, fichier, peu importe), alors pourquoi ne pouvez-vous pas compter sur le système pour le fermer pour vous quand le niveau le plus bas de la ressource est gced? Si le serveur à l'autre extrémité absolument besoin de vous pour fermer la connexion proprement plutôt que de simplement déposer le socket, puis ce qui va arriver si quelqu'un trébuche sur le câble d'alimentation de la machine, votre code est en cours d'exécution, ou l'intervenant du réseau?

Avertissement: j'ai travaillé sur une JVM mise en œuvre dans le passé. Je déteste les finaliseurs.

56voto

Tom Points 15618

Une règle simple: ne jamais utiliser des outils de finalisation. Le seul fait qu'un objet a un finaliseur (peu importe quel code il s'exécute) est suffisant pour provoquer une surcharge pour la collecte des ordures.

À partir d'un article de Brian Goetz:

Les objets avec les finaliseurs (ceux qui avoir un non-trivial méthode finalize ()) ont des frais généraux par rapport à des objets sans les finaliseurs, et devrait être utilisés avec parcimonie. Finalizeable les objets sont à la fois plus lents à allouer et plus lente à se recueillir. Au moment de la répartition le temps, la JVM doit s'inscrire tout finalizeable objets avec les ordures collecteur, et (au moins dans le HotSpot JVM) finalizeable objets doivent suivre un ralentissement de la répartition chemin que la plupart des autres objets. De même, finalizeable les objets sont plus lents à recueillir, trop. Il prend au moins deux de collecte des ordures cycles (dans le meilleur des cas) devant un finalizeable objet peut être récupéré et le garbage collector a à faire un travail supplémentaire pour invoquer le finalizer. Le résultat est plus de temps passé l'allocation et de la collecte des objets et plus de pression sur la poubelle collector, car la mémoire utilisée par inaccessible finalizeable objets est conservés plus longtemps. Combinez cela avec la fait que les finaliseurs ne sont pas garanti pour fonctionner dans tous les prévisible le temps, ou même à tous, et vous pouvez voir qu'il y a relativement peu de des situations pour lesquelles la finalisation est le bon outil à utiliser.

50voto

skaffman Points 197885

La seule fois où j’ai utilisé finaliser en production code consistait à mettre en place un contrôle de ressources d’une donnée de l’objet avaient été nettoyés et si non, puis ouvrez une session un message très bruyante. Il n’a pas réellement essayer et le faire lui-même, il juste a crié beaucoup si cela n’a pas été fait correctement. S’est avéré être très utile.

39voto

Paul Tomblin Points 83687

J’ai fait Java professionnellement depuis 1998, et je n’ai jamais implémenté finalize(). Pas une seule fois.

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