C'est une sorte d'étrange, mais le code parle plus que des mots, alors regardez le test pour voir ce que je fais. Dans ma configuration actuelle (Java 7 Mise à jour 21 sous Windows 64 bit) Ce test échoue avec ArrayIndexoutofboundSException, mais le remplacement du code de méthode de test avec le code commenté, le fonctionnement. Et je me demande s'il y a une partie de la spécification Java qui expliquerait pourquoi.
Il me semble que "Michael Nesterenko" suggère que la valeur du champ de tableau est mise en cache dans la pile, avant d'appeler la méthode, et non mis à jour le retour de l'appel. Je ne peux pas dire s'il s'agit d'un bug JVM ou d'une "optimisation" documentée. Pas de multi-filetage ou "magique" impliqué. P>
3 Réponses :
Comparer le code Java compilé à l'aide de CODE COMMENTAIRE: P> Javap -C TestaioOOOOOOOOB CODE>
public void testGrow();
Code:
0: aload_0
1: ldc #6; //String test
3: invokespecial #7; //Method grow:(Ljava/lang/String;)I
6: istore_1
7: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream;
10: aload_0
11: getfield #3; //Field array:[Ljava/lang/String;
14: iload_1
15: aaload
16: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
19: return
Cela explique le comportement, mais cela n'explique pas pourquoi il a été compilé comme ça. Il doit y avoir quelque chose dans les JLS ...
Ceci est bien défini par Spécification de la langue Java : évaluer x [y] code>, premier
x code> est évalué, puis
y code> est évalué. Dans votre cas,
x code> évalue vers une chaîne
[] code> avec zéro éléments. Ensuite,
y code> modifie une variable de membre et évalue à
0 code>. Essayer d'accéder à l'élément du 0ème de la matrice déjà retournée échoue. Le fait que le membre
modifications code> n'a aucune incidence sur la recherche de tableau, car nous envisageons la chaîne
[] code> que
array code> référencé à le temps que nous l'avons évalué. p>
Là-bas comme la première balle sur le lien. Excellent.
Ce comportement est mandaté par les JLS. Par 15.13.1 A > "," Une expression d'accès au tableau est évaluée à l'aide de la procédure suivante: Premièrement, l'expression de référence de la matrice est évaluée. Si cette évaluation est terminée brusquement, l'accès à la matrice se termine brusquement pour la même raison et l'expression d'index n'est pas évaluée. Sinon, le L'expression d'indice est évaluée. [...] ". P>
Juste une suppose, lorsque vous appelez
grandir code> à partir de tableau, il est déjà en pile et donc le lien n'est pas mis à jour, mais si vous appelez
GROGUER code> avant, puis utilisez l'index, lien vers le tableau est chargé après la mise à jour et cela fonctionne donc. Juste une supposition. Peut-être que regarder le code des octets pourrait aider
Je ne l'appellerais pas "mis en cache dans la pile". Je pense que c'est une question java (la langueuse). Vous référencez un nom, qui est résolu avant i> en utilisant / appliquant la valeur résolue associée à celle-ci. Donc, si le nom est réaffecté entre les deux, vous avez la mauvaise valeur.
Voici un cas d'essai plus simple:
Classe publique TestaioOB {Objet statique [] Array; static int réassigne () {array = nouvel objet [] {nouvel objet ()}; retour 0; } Void statique public principal (chaîne [] args) {system.out.println (réaffectation (réaffectation ()]); }} code>. Cela jette (comme si cela devrait), et vous demandez pourquoi.
Il convient de mentionner que ce n'est pas seulement Java. La référence de tableau est évaluée avant l'appel code> Appel code> JavaScript ( exemple ), C # ( exemple ), et c ( Exemple ) également, et probablement d'autres mais je ne les essayais pas. (Vous pouvez exécuter l'un ou l'autre de ces deux derniers en ligne ici: compileonline.com )