Veuillez vous reporter au code Java ci-dessous: La sortie vue est la suivante: p> Je pense que var = 0 se produit parce que l'objet est à moitié initialisé; Semblable à ce que Skeet Jon dit ici P> Mes questions sont les suivantes: p> Pourquoi la méthode remplacée est-elle appelée si l'objet de classe dérivé n'est pas encore créé? P> à quel moment-là est varié de la valeur attribuée 0? P > Y a-t-il des cas d'utilisation dans lesquels un tel comportement est souhaité? P> P>
4 Réponses :
Le Ce comportement au moins conduit à la cohérence, mais cela peut être une douleur. En termes de cohérence, supposons que vous ayez une sous-classe en lecture seule d'une classe de base mutable. La classe de base peut avoir une propriété Quelques lignes directrices: P>
Essayez de ne pas faire beaucoup de travail dans un constructeur. Une façon d'éviter que ceci est de travailler dans une méthode statique, puis effectuez la dernière partie de la méthode statique un appel de constructeur qui définit simplement des champs. Bien sûr, cela signifie que vous n'obtiendrez pas les avantages du polymorphisme pendant que vous faites le travail - mais ce faisant dans un appel de constructeur serait dangereux de toute façon. P> Li>
Essayez très difficile d'éviter les appels vers des méthodes non finales lors d'un constructeur - il est très susceptible de provoquer une confusion. Documenter toute méthode des appels que vous avez vraiment avez em> pour faire très em> clairement, afin que quiconque leur prenne saillie qu'ils seront appelés avant l'initialisation terminée. P> LI>
Si vous devez appeler une méthode pendant la construction, il est généralement em> pas alors approprié de l'appeler ensuite. Si tel est le cas, documentez-le et tente de l'indiquer dans le nom. P> LI>
Essayez de ne pas dépasser l'héritage en premier lieu - cela ne va pas devenir un problème lorsque vous avez une sous-classe dérivant d'une superclasse autre que l'objet :) La conception de l'héritage est délicate. P> li>
ul> OBJECT CODE> OBJECT a été créé - c'est juste que le constructeur n'a pas encore été exécuté. Le type d'objet ne change jamais dans Java après que l'instant est créé, ce qui se passe avant que tous les constructeurs s'épuent. P> li>
var code> est attribué la valeur par défaut de 0 dans le processus de création d'un objet, avant que les constructeurs ne soient exécutés. Fondamentalement, la référence de type est définie et le reste de la mémoire représentant l'objet est essuyé à zéro (conceptuellement, de toute façon - il peut déjà avoir été essuyé à zéro avant, dans le cadre de la collecte des ordures) p> li>
Ismutable () code> qui a été effectivement défaillante sur true - mais la sous-classe lavérifie pour toujours retourner false. Il serait étrange que l'objet soit mutable avant que le constructeur de sous-classe ne courait, mais immutaculable ensuite. D'autre part, c'est définitivement em> étrange dans les situations où vous finissez par exécution de code dans une classe avant que le constructeur de cette classe ait fonctionné: ( P> LI>
ul>
Dans Swing, il est courant d'exécuter Créer code> la méthode dérivée avant que le constructeur [corps] ait fonctionné. Swing est définitivement i> étrange.
@TOM, ce qui signifie que la méthode créer code> peut ne jamais dépendre de l'état de l'objet de la classe dérivée.
@RSP YUP. Cela dépendra généralement du type de la classe dérivée. Il peut en réalité dépendre de l'état introduit à partir d'un "code extérieur ce code>" ou via un piratage tel que threadlocal code>.
Merci pour l'explication cogent!
Il existe certaines propriétés de la spécification de langue Java qui devrait être notée afin d'expliquer ce comportement: P>
La séquence des événements est la suivante: p>
En bref, chaque fois qu'un constructeur d'une superclasse invoque une méthode non finale, nous avons le risque potentiel d'entrer dans ce piège, ce qui ne le fait pas non plus recommandé. Notez qu'il n'y a pas de solution élégante si vous insistez sur ce modèle. Voici 2 autres complexes et créatifs, à la fois nécessitant une synchronisation de fil (!): P>
Ce n'est pas vraiment la raison, car l'ordre de construction est le même en C ++. Je ne vois pas comment ça pourrait jamais être différent réellement. Pourtant, cette question ne se pose pas en C ++. La véritable raison est que l'objet est du type cible tout au long de la construction, qui n'est pas i> l'affaire en C ++.
@EJP: Je ne comparais pas avec C ++. Tout ce que je suis insulte, c'est que deux faits causent ce comportement: 1) Le SUPER'S COR est toujours appelé premier 2) Un appel à une méthode de la CTOR n'est pas différent de tout appel, il s'agit donc d'un appel virtuel à moins que la méthode est finale ( privé / déclaré comme final). Voir les liens que j'ai fournis pour plus de détails sur ce problème de conception.
Je suis d'accord avec les faits deux i>, maintenant vous les avez dit à la fois ;-)
Pourquoi la méthode remplacée est-elle appelé si l'objet de classe dérivé n'est pas encore créé? P> blockQuote>
dérivé code> Constructeur de classe appelle implicitement le constructeur de la classe code> code> comme première instruction.BASE CODE> Constructeur de classeMéthode () CODE> QUI INVOTE La mise en œuvre répandue dans la classe CODE> DROITE CODE> car c'est la classe dont l'objet est créé.méthode () code> dansdérivé code> classe voitvar code> comme 0 à ce point. p>à quel moment-là est Var attribué Valeur 0? P> blockQuote>
var code> est attribué la valeur par défaut pourint code> type I.e. 0 avant que le controeur dedérivé code> classe est invoqué. Il est attribué la valeur de 2après strong> l'appel de la contruceur de superclasse implicite a fini et avant forte> les énoncés dans dérivé code> constructeur de classe commence à exécuter. P >Y a-t-il des cas d'utilisation où de tels Le comportement est souhaité? P> blockQuote>
Il s'agit généralement d'une mauvaise idée d'utiliser non-
final code> non-Méthodes privées code> dans les constructeurs / initialiseurs d'un autreclassique code> classe . Les raisons sont évidentes dans votre code. Si l'objet créé est une instance de sous-classe, les méthodes peuvent donner des résultats inattendus. P>
Notez que cela est différent de C ++, où le type change alors que l'objet est en cours de construction, de sorte que l'appelant une méthode virtuelle à partir des constructeurs de classe de base n'appelle pas le remplacement de la classe dérivée. La même chose arrive à l'inverse pendant la destruction. Donc, cela peut être un petit piège pour les programmeurs C ++ venant à Java. P>
Oui, toujours bon de savoir que le type peut changer en C ++ et ne peut pas en Java.
Voir aussi: Stackoverflow.com/Questtions/3288601/... < / a>
@Zaki: Merci pour le lien. Appréciez-le ...