Par curiosité,
Pourquoi le modificateur d'accès de la méthode finalize()
est-il fait comme protected
. Pourquoi ça ne peut pas être public
? Quelqu'un peut-il m'expliquer une raison précise derrière cela?
De plus, j'ai appris que la méthode finalize()
n'est appelée qu'une seule fois. Si je l'appelle deux fois dans mon programme en interne, que se passe-t-il? Le garbage collector appellera-t-il à nouveau?
private void dummyCall() {
try {
finalize();
finalize();
} catch (Throwable e) {
e.printStackTrace();//NOT REACHES EXCEPTION
}
}
Je réponds à votre question par une autre question:
Pourquoi la méthode
finalize
ne doit pas être protégée?
En général, vous devriez essayer de garder les choses aussi privées que possible. C'est à cela que sert l'encapsulation. Sinon, vous pourriez tout faire public
. finalize
ne peut pas être private
(puisque les classes dérivées devraient pouvoir y accéder pour pouvoir le remplacer), donc il devrait au moins être protected
mais pourquoi donner plus d'accès quand ce n'est pas souhaitable?
Après avoir lu votre commentaire plus attentivement, je suppose que je vois maintenant votre point principal. Je pense que votre point est que tout découle de Java.lang.Object
et, par conséquent, accède à ses membres protected
, cela ne ferait aucune différence pour lui (ou toute méthode dans Java.lang.Object
d'ailleurs) soit public
par opposition à protected
. Personnellement, je considérerais cela comme un défaut de conception en Java. Ceci est en effet corrigé en C #. Le problème n'est pas pourquoi finalize
est protégé. C'est bon. Le vrai problème est que vous ne devriez pas être en mesure d'appeler des méthodes protégées dans la classe de base via une référence d'objet du type de classe de base. Eric Lippert a une entrée de blog discutant pourquoi autoriser un tel accès aux membres protégés est une mauvaise idée qui est plus de détails sur Stack Overflow dans cette question .
Pourquoi le modificateur d'accès de la méthode finalize () est-il protégé? Pourquoi ne peut-il pas être public?
Il n'est pas public car il ne doit être invoqué par personne d'autre que la JVM. Cependant, il doit être protégé afin qu'il puisse être remplacé par des sous-classes qui doivent définir un comportement pour lui.
Si je l'appelle deux fois dans mon programme, que se passe-t-il en interne?
Vous pouvez l'appeler comme vous voulez, c'est juste une méthode après tout. Cependant, tout comme public static void main(String [] args)
, il a une signification particulière pour la JVM
Le garbage collector appellera-t-il à nouveau?
Oui
Rant contre finaliser ()
Méfiez-vous des erreurs dans les déclarations ci-dessus, je suis un peu fatigué :-)
Découvrez ce lien qui en parle.
Fondamentalement, il serait plus logique que ce soit private
, car il ne devrait être appelé que par la JVM (garbage collector). Mais pour permettre à une sous-classe d'appeler la méthode parent finalize()
dans le cadre de sa finalize()
, elle doit être protected
.
( Edit - Et juste une mise en garde générale - l'utilisation de la méthode finalize () est généralement déconseillée car il n'y a aucun moyen de s'assurer qu'elle sera jamais appelée. Bien que cela ne signifie pas que vous n'aurez jamais l'occasion de l'utiliser - c'est juste rare.)
La partie concernant finalize()
appelée une seule fois ne s'applique qu'aux appels du GC. Vous pouvez imaginer l'objet comme ayant un drapeau caché "finalize()
a été appelé par le GC", et le GC vérifie ce drapeau pour savoir quoi faire avec l'objet. Le drapeau n'est en aucun cas affecté par vos propres appels faits à la main à finalize()
.
Lors de la finalisation, lisez cet article de Hans Boehm (qui est bien connu pour son travail sur la collecte des ordures). C'est une révélation sur la finalisation; en particulier, Boehm explique pourquoi la finalisation est nécessairement asynchrone. Un corollaire est que si la finalisation est un outil puissant, elle est très rarement le bon outil pour un travail donné.
Ce n'est pas public
(ou accès par défaut) car il est destiné à être appelé par la JVM en interne lorsque l'objet est récupéré - c'est pas destiné à être appelé par autre chose. Et ce n'est pas private
car il est censé être remplacé et vous ne pouvez pas remplacer les méthodes privées.
Si je l'appelle deux fois dans mon programme, que se passe-t-il en interne? Le garbage collector appellera-t-il à nouveau?
Probablement oui, mais il est difficile d'imaginer un scénario où cela aurait un sens - le point de finalize()
est de faire le nettoyage quand un objet est récupéré. Et cela ne fait même pas très bien, c'est donc quelque chose que vous devriez éviter complètement plutôt que d'expérimenter.
finalize () n'est utilisé par la JVM que pour nettoyer les ressources lorsque l'objet est collecté. Il est raisonnable pour une classe de définir les actions à entreprendre sur la collection, pour lesquelles elle peut avoir besoin d'accéder à super.finalize (). Il n'est pas vraiment logique qu'un processus externe appelle finalize (), car un processus externe n'a pas de contrôle sur le moment où l'objet est collecté.
De plus, j'ai appris que la méthode finalize () n'est appelée qu'une seule fois. Si je l'appelle deux fois dans mon programme, que se passe-t-il en interne?
Vous vous posez probablement cette question sous l'impression de destructeurs C++. Dans Java finalize () ne fait aucune magie (comme effacer la mémoire). Elle est censée être appelée par le garbage collector. Mais pas l'inverse.
Je vous recommande de lire le chapitre correspondant dans "Effective Java" de Joshua Bloch. Il indique que l'utilisation des finaliseurs est une mauvaise pratique et peut entraîner des problèmes de performances et d'autres problèmes, et il n'y a que plusieurs cas où ils doivent être utilisés. Le chapitre commence par les mots suivants:
Les finaliseurs sont imprévisibles, souvent dangereux et généralement inutiles.
Je pense que la raison pour laquelle finalize
est protégé serait que peut-être il est écrasé par certaines classes du JDK, et ces méthodes écrasées sont appelées par JVM.