Pourquoi la méthode finalize() en java.lang.Objet “protégés”?
Par curiosité,
Pourquoi le finalize()
méthode de modificateur d'accès est faite comme protected
. Pourquoi ne peux-il être public
? Quelqu'un peut-il m'expliquer une raison derrière tout cela?
Aussi, je suis venu pour savoir que finalize()
méthode est appelée qu'une seule fois. Si je l'appelle deux fois dans mon programme en interne, ce qui se passe? Sera le garbage collector appel de ce nouveau?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
- pourquoi voulez-vous écrire une méthode à invoquer finalize(). finalize() est invoquée à l'exemple de la destruction par la JVM. vous ne devriez pas l'invoquer. Vous pouvez la remplacer si, dans le cas où vous voulez un comportement particulier à la destruction du temps...
- Oui. Personnellement, je ne ferais jamais cela. Mais j'ai demandé par curiosité depuis que j'ai lu GC coutume de l'appeler si sa déjà appelée sur un objet. Qui est de garder la trace de savoir si cette méthode finalize() est appelée ou non est ce que mon doute. Je n'ai pas une explication convaincante à cette deuxième question.
- La vraie question intéressante est: pourquoi est-finalize() présente dans la partie supérieure de la Java OO hiérarchie? 200K LOC projet ici et nous n'avons pas remplacé finalize() une seule fois. Certains vont jusqu'à dire que c'est une odeur de code pour remplacer finalize() et certains hérétiques serait aller aussi loin que de dire que finalize() n'existe pas à l'OOA/OOD niveau et que sa présence au sommet de la Java de la hiérarchie est un (cassé) Java idiosynchrasy (et complètement étrangers à votre espace-problème). Tout à fait certains de la upvoted réponses ici btw envisager finalize() pour être cassée ou défectueuse d'une manière ou d'une autre 🙂
- Seuls les experts en Java devraient être aller n'importe où près de finalize().
- "GC coutume de l'appeler si sa déjà appelée sur un objet. Qui est de garder la trace de savoir si cette méthode finalize() est appelée ou non ..." Err, GC est de garder la trace? Et une fois que l'objet tombe entre les mains de les GC vous n'avez pas une façon d'attirer l'finalize() de vous-même. Vraiment votre question n'a aucun sens.
- "La vraie question intéressante est: pourquoi est-finalize() présente dans la partie supérieure de la Java OO hiérarchie?' Euh, donc, GC peut appeler ça sur n'importe quel objet?
- Juste parce que vous voudrez peut-être appeler finalize() sur certains objets, ne signifie pas qu'ils ont tous besoin. Comment sur une interface et si vous voulez que le GC à l'appel, vous pouvez dire
implements finalize
sur votre classe. Aussi, la seule chose que vous devriez être en mesure de faire à finaliser est le journal que certains membre de la variable != null parce que quelqu'un n'a pas écrit le bonfinally
bloc.
Vous devez vous connecter pour publier un commentaire.
Je réponds à votre question par une autre question:
En général, vous devriez essayer de garder les choses aussi bien privée que possible. C'est ce que l'encapsulation est tout au sujet. Sinon, vous pourriez faire tout
public
.finalize
ne peut pas êtreprivate
(depuis les classes dérivées doivent être en mesure d'y accéder pour être en mesure de le remplacer), il devrait au moins êtreprotected
mais pourquoi donner plus d'accès lorsqu'il n'est pas souhaitable?Après la lecture de votre commentaire avec plus de soin, je suppose que je vois votre point principal maintenant. Je pense que votre point est, puisque tout ce qui dérive de
java.lang.Object
et, par conséquent, accède à sonprotected
membres, il ne serait pas faire une différence pour elle (ou n'importe quelle méthode dejava.lang.Object
d'ailleurs) pour êtrepublic
par opposition àprotected
. Personnellement, j'avais le compter comme un défaut de conception en Java. C'est en effet fixé en C#. Le problème n'est pas pourquoifinalize
est protégé. C'est OK. Le vrai problème est que vous ne devriez pas être en mesure d'appeler les méthodes protected dans la classe de base par l'intermédiaire d'un objet de référence de la classe de base type. Eric Lippert a un l'entrée de blog discuter pourquoi le fait de permettre ce genre d'accès aux membres protégés est une mauvaise idée qui est des précisions sur un Débordement de Pile dans cette question.private abstract
serait une contradiction dans les termes.new BaseType().ProtectedMethod()
ne fonctionne pas dansDerivedClass
en C#. Cela rendprotected
membres sont bienprivate
à d'autres "branches" de l'arbre d'héritage.protected void finalize() throws Throwable { }
Il n'est pas public, car il ne devrait pas être invoquée par toute personne autre que la JVM. Cependant, il doit être protégé de sorte qu'il peut être remplacée par des sous-classes qui en ont besoin pour définir un comportement pour elle.
Vous pouvez l'appeler ce que vous voulez, c'est juste une méthode, après tout. Toutefois, à l'instar de
public static void main(String [] args)
, il a une signification spéciale pour la JVMOui
super.finalize()
lorsque vous la remplacez.Diatribe contre finalize()
Méfiez-vous des erreurs dans les déclarations ci-dessus, je suis un peu fatigué 🙂
Finalize
; n'avaient-ils pas été, quelque chose ressemblant à AutoCloseable aurait été une partie de Java 1.0. Si la langue est un moyen de distinguer entre les références qui encapsulent la propriété des ressources et ceux qui ne sont qu'à identifier les ressources détenues par quelqu'un d'autre, je ferais l'hypothèse que 99% des ressources de nettoyage pourraient être automatisées de manière déterministe, parce que 99% des entités nécessitant nettoyage, à tous les moments de leur vie, ont exactement la même propriétaire. Pas toujours le même propriétaire, mais jamais de zéro et de ne jamais les deux.Découvrez ce lien qui en parle.
Fondamentalement, il ferait le plus de sens pour être
private
, comme il ne doit être appelée que par la JVM (garbage collector). Mais afin de permettre une sous-classe d'appeler le parentfinalize()
méthode dans le cadre de sonfinalize()
, il doit êtreprotected
.(Modifier - Et juste une mise en garde générale - utilisation de la méthode finalize() est généralement pas recommandée, car il n'y a aucun moyen de s'assurer qu'il ne sera jamais appelé. Bien que cela ne signifie pas que vous n'aurez jamais l'occasion d'utiliser, c'est juste rare.)
La partie sur
finalize()
être appelé qu'une seule fois ne s'applique qu'aux appels de la GC. Vous pouvez imaginer l'objet que d'avoir caché drapeau "finalize()
a été appelé par le GC", et la GC vérifier que l'indicateur de savoir quoi faire avec l'objet. Le drapeau n'est pas affecté en aucune façon par votre propre main les appels àfinalize()
.Sur la finalisation, lire cet article de Hans Boehm (qui est bien connu pour son travail sur la collecte des ordures). C'est une révélation à propos de finalisation; en particulier, Boehm explique pourquoi la finalisation est nécessairement asynchrone. Un corollaire est que, bien que la finalisation est un outil puissant, il est très rarement le bon outil pour un travail donné.
Ce n'est pas
public
(ou d'accès par défaut) parce qu'il est destiné à être appelé par la JVM en interne lorsque l'objet est à la ramasse miettes - c'est pas destinés à être appelé par n'importe quoi d'autre. Et ce n'est pasprivate
parce qu'il est destiné à être remplacé, et vous ne pouvez pas remplacer les méthodes privées.Oui, probablement, mais il est difficile d'imaginer un scénario où ce serait faire toute sorte de sens du point de
finalize()
est de faire le nettoyage lorsqu'un objet est des ordures collectées. Et il n'a même pas le faire bien, donc c'est vraiment quelque chose que vous devriez éviter complètement, plutôt que d'expérimenter avec.finalize() est seulement utilisé par la JVM pour nettoyer les ressources lorsque l'objet est collecté. C'est raisonnable pour une classe pour définir quelles mesures devraient être prises sur la collection, pour laquelle il peut avoir besoin d'accéder super.finalize(). Il n'a pas vraiment de sens pour un processus extérieur à l'appel finalize(), puisque, en dehors du processus n'ont pas de contrôle sur le moment où l'objet est collecté.
Vous demandez sans doute ce sous l'impression de C++ ~destructeurs. En java de la méthode finalize () ne fait pas de la magie (comme l'effacement de la mémoire). C'est censé être appelé par le garbage collector. Mais pas vice-versa.
Je vous recommandons de lire le chapitre correspondant dans Joshua Bloch est "Effective Java". Il est dit que l'utilisation des outils de finalisation est une mauvaise pratique et peut causer de la performance et d'autres questions, et il y a que quelques cas où ils devraient être utilisés. Le chapitre commence avec les mots suivants:
Je pense que la raison pour laquelle
finalize
est protégé serait que c'est peut-être remplacée par certaines classes du JDK, et ces méthodes de remplacement sont appelés par la JVM.