6
votes

Y a-t-il une différence entre l'attribution directe d'une variable finale et d'attribuer une variable finale dans le constructeur?

y a-t-il une différence entre ces deux initialisations de la valeur de la variable finale ? xxx

et xxx p > -

EDIT: Exemple plus complexe, impliquant des sous-classes. "0" est imprimé sur STDOUT dans ce cas, mais 7 est imprimé si j'ignore la valeur directement. xxx


6 commentaires

Cet exemple est un peu obscur: où est addPropertyChangelisener () appelé?


@Viruzzo Je soupçonne que cela s'appelle dans le constructeur de JcheckBox ou JComponent ou ... Le code est un exemple supprimé d'un composant de Jcheckbox personnalisé Je suis en train de construire, qui possède des propriétés spéciales (comme quelques propriétés supplémentaires pour lesquelles je veux être capable d'enregistrer le bien-au bienChangelisteners)


Pour que le constructeur de la superclasse appelle une méthode de la sous-classe, ce serait une erreur, si possible. Cet exemple est probablement imparfait en raison de l'utilisation de JFRAME et de possibles problèmes de concurrence.


@Viruzzo AddPropertyChangelistener est une méthode virtuelle (de même que toutes les méthodes de Java) afin que le constructeur de Superclasses appelle textbox.addpropertychangelistener si elle appelle AddPropertyChangelistener du tout. Ou puis-je avoir quelque chose de mal? Quelles questions de concurrence envisagez-vous, concernant le fil d'événement AWT (puisque je ne reproget pas d'autres threads)?


La valeur de cas = 0 n'est possible que le testbox.addpropertychangelistener () est appelée à l'intérieur de Testbox.super () et qui ressemble à un comportement très étrange, ou ... Avez-vous essayé d'utiliser des accolades simples au lieu de doubles dans le JFrame et Initialisation JPanel? Je ne peux pas vérifier en ce moment, mais cela pourrait être significatif.


J'ai modifié le deuxième exemple pour être un peu moins obscur. Mêmes effets.


7 Réponses :


0
votes

Autre que dans le second cas, vous pouvez affecter une valeur différente basée sur laquelle le constructeur a été appelé ou quels paramètres ont été transmis, no.


3 commentaires

Est-ce que cela tient toujours, c'est-à-dire pour les sous-classes?


@scravy: Les sous-classes constructeur devront appeler Super (...), qui initialisera le champ final basé sur l'argument transmis à Super (...). Alors oui, il contient des sous-classes


J'ai ajouté un autre exemple impliquant des sous-classes que je ne peux absolument pas expliquer alors (autre que cela reste quelque chose d'étrange avec JCHECKBOX).



0
votes

Non, il n'y a pas. La seule différence est la commande utilisée pour initialiser les champs: les champs initialisés directement sont initialisés avant ceux initialisés dans le constructeur.


0 commentaires

0
votes

Je ne pense pas qu'il y ait une différence. Mais la valeur dont vous avez besoin pourrait vous aider à décider qui à utiliser.

  1. Si la variable est finale et assignée à une valeur fixe dans le constructeur, il n'est pas nécessaire de l'affecter dans le constructeur.
  2. Si la variable est définitive et attribuée à différentes valeurs, passée sous forme d'argument, dans le constructeur, vous devez l'affecter dans le constructeur.

    La plupart du temps, le premier cas est utilisé. Parce que dans la mesure où je sais que les variantes finales ne sont que les constantes.


0 commentaires

0
votes

Un constructeur s'exécute dans l'ordre suivant:

  1. Super () est appelé.
  2. Les variables locales sont initialisées et des blocs d'initialisateur anonymes {} sont appelés.
  3. Le code dans le constructeur lui-même est appelé. Notez que si le constructeur appelle explicitement super () lui-même, cela est pris en charge sous la n ° 1.

    Ainsi, la réponse à votre question est que l'initialisation serait déplacée de N ° 2 dans la version de la Déclaration-avec Initializer à # 3 dans la version Initialize-in-Constructor. Toutefois, sauf si vous avez des blocs d'initialiseur anonyme {} ou éventuellement des champs initialisés à l'aide d'initialisations antérieures d'autres champs, il serait impossible de dire la différence.


3 commentaires

Donc, Super () (# 1) est même appelé avant l'affectation directe la valeur INT finale = 7; (n ° 2)?


@Scravy (n ° 1) Yes (# 2) champs, pas variables mais vous obtenez l'idée; Les blocs d'initialisation sont identiques aux blocs d'initialiseur statiques, mais pour les instances: vous mettez fondamentalement du code entre {} en dehors de toute méthode, et elle est appelée à l'étape 2.


@EJP J'ai ajouté un autre exemple impliquant une sous-classe appelante super. Si je vous ai raison, super () doit être appelé avant l'initialisation de la valeur de chaque sens, mais je vois 0 une fois, et si j'ignais la variable directement.



4
votes

Il y a une différence dans le niveau de code octet:

code source: p> xxx pré>

produit du code suivant de addPropertychangelistener p>: P> xxx pré>

et code source: p>

   0:   getstatic       #3; 
   3:   bipush  7
   5:   invokevirtual   #4; 


3 commentaires

Wuow. Merci pour le démontage. Que petite différence souffle réellement un composant entier dans mon logiciel (ce n'est qu'un exemple supprimé que j'ai posté ici).


explose? C'est étrange, car la fonctionnalité devrait être la même. Seules des différences de vitesse et d'utilisation de la mémoire peu importantes doivent survenir.


Dans le code complet, il existe un objet de propriétéChangeSupport qui n'est pas encore créé lorsque la méthode AddPropertyChangelistener () est invoquée. J'accède maintenant à cela que si ce n'est pas NULL, car sinon j'ai une NPE lors de la création de la case à cocher. Je me demandais simplement comment cela peut être.



1
votes

Une interprétation erronée courante d'une variable finale est qu'elle ne peut pas changer sa valeur. La signification réelle du modificateur final (JLS 4.5.4) est que "une variable finale ne peut être attribuée qu'une fois".

Vous avez rencontré l'une des situations où il est possible d'évaluer une variable "finale vierge" (déclarée, mais pas encore assignée), de sorte qu'elle évalue la valeur par défaut du type de données spécifié, même si sa plus tard a attribué une valeur différente.


0 commentaires

2
votes

essayé avec un exemple très simple et oui, lorsque la valeur est accessible dans le constructeur du parent, il est unialisalisé (comme il devrait être), sauf si c'est final et initialisé quand déclaré. Le processus est décrit par EJP, mais avec une étape n ° 0: les finales sont initialisées avec la valeur spécifiée, le cas échéant.


0 commentaires