Après un tas de spec de la lecture et de la pensée, j'en ai conclu que:
Dans une Java 5 ou Java 6 compilateur, c'est le comportement correct. Chapitre 16 "Certaine Affectation de La Java Language Specification, Troisième Édition , dit:
Chaque variable locale (§14.4) et tous les espaces final
(§4.12.4) domaine (§8.3.1.2) doit avoir un certainement affecté de la valeur lors de tout accès de sa valeur se produit. Un accès à sa valeur consiste en la simple nom de la variable n'importe où dans une expression, sauf que la gauche opérande de la simple opérateur d'assignation =
.
(l'emphase est mienne). Ainsi, dans l'expression 2 * this.x
, this.x
partie n'est pas considéré comme un "accès de [x
s'] valeur" (et n'est donc pas soumis aux règles d'une certaine affectation), car this.x
n'est pas le simple nom de la variable d'instance, x
. (N. B. la règle lors de l'affectation définitive se produit, dans le paragraphe après la citée ci-dessus le texte, ne permettent quelque chose comme this.x = 3
, et considère x
définitivement d'être affectées par la suite; c'est seulement la règle pour les accès qui ne compte pas this.x
.) Notez que la valeur de this.x
dans ce cas sera de zéro, par §17.5.2.
Dans Java 7 compilateur, c'est un bug du compilateur, mais compréhensible. Chapitre 16 "Certaine" d'Assignation de la Java Language Specification, Java 7 Édition SE dit:
Chaque variable locale (§14.4) et tous les espaces final
domaine (§4.12.4, §8.3.1.2) doit certainement affecté de la valeur lors de tout accès de sa valeur se produit.
Un accès à sa valeur consiste en la simple nom de la variable (ou, pour un champ, le simple nom de domaine qualifié en this
) n'importe où dans une expression, sauf que la gauche opérande de la simple opérateur d'assignation =
(§15.26.1).
(l'emphase est mienne). Ainsi, dans l'expression 2 * this.x
, this.x
partie doit être considérée comme un "accès à l' [x
s'] valeur", et devrait donner une erreur de compilation.
Mais vous ne vous demandez pas si le premier devrait compiler, avez-vous demandé pourquoi il ne la compilation (dans certains compilateurs). Ce n'est pas nécessairement spéculative, mais je vais faire deux suppositions:
- La plupart des compilateurs Java 7 ont été écrits par la modification de la version 6 de Java compilateurs. Certains compilateur écrivains peuvent ne pas avoir remarqué ce changement. En outre, de nombreux Java-7 compilateurs et des IDEs encore le support de Java 6, et certains compilateur écrivains peuvent ne pas avoir senti motivé pour spécifiquement rejeter quelque chose en Java-7 mode qu'ils acceptent en Java-6 mode.
- Le nouveau Java 7 comportement est étrange incohérence. Quelque chose comme
(false ? null : this).x
, est encore autorisé, et pour cette question, de même (this).x
, est encore autorisé; c'est seulement le jeton de la séquence de this
plus .
plus le nom de zone qui est affecté par ce changement. Accordé, une telle incohérence existait déjà sur le côté gauche d'une instruction d'affectation (on peut écrire this.x = 3
, mais pas (this).x = 3
), mais c'est plus facilement compréhensible: c'est en acceptant this.x = 3
spéciale du permis de cas de l'autre interdit la construction obj.x = 3
. Il est logique de le faire. Mais je ne pense pas que cela a du sens pour rejeter 2 * this.x
spécial interdit de cas de la par ailleurs permis la construction 2 * obj.x
, étant donné que (1) cette spéciale interdit de cas est facilement contourné en ajoutant entre parenthèses, que (2) cette spéciale interdit de cas a été autorisé dans les versions précédentes de la langue, et que (3) nous avons encore besoin de la règle spéciale en vertu duquel final
les champs ont des valeurs par défaut (par exemple, 0
d'un int
) jusqu'à ce qu'ils sont initialisés, à la fois parce que des cas comme (this).x
, et parce que des cas comme this.foo()
où foo()
est une méthode qui accède x
. Ainsi, certains compilateur écrivains peuvent ne pas avoir senti motivé pour faire cette incompatible changement.
L'un de ces serait étonnant — je suppose que le compilateur écrivains avaient des informations détaillées sur chaque changement de la spécification, et dans mon expérience, compilateurs Java sont généralement assez bon pour coller à la spécification exactement (contrairement à d'autres langues, où chaque compilateur a son propre dialecte) — mais, bien, quelque chose est arrivé, et le ci-dessus sont mes deux seules des suppositions.