J'ai noté une différence dans le comportement de déballage automatique entre Java SE 6 et Java SE 7. Je me demande pourquoi, car je ne trouve aucune documentation sur les changements de ce comportement entre ces deux versions.
Voici un exemple simple:
Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Cela compile bien avec javac de Java SE 7. Cependant, si je donne au compilateur l'argument "-source 1.6", j'obtiens une erreur sur la dernière ligne:
inconvertible types
found : java.lang.Object
required: int
J'ai essayé de télécharger Java SE 6 pour compiler avec le compilateur natif de la version 6 (sans aucune option -source). Il accepte et donne la même erreur que ci-dessus.
Alors qu'est-ce qui donne? À partir d'un peu plus d'expérimentation, il semble que le déballage dans Java 6 ne peut déballer que des valeurs qui clairement (au moment de la compilation) sont du type encadré. Par exemple, cela fonctionne dans les deux versions:
Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Il semble donc qu'entre Java 6 et 7, la fonctionnalité de déballage a été améliorée afin de pouvoir convertir et déballer des types d'objets en un seul coup, sans savoir (au moment de la compilation) que la valeur est du type encadré approprié. Cependant, en lisant la spécification du langage Java ou les articles de blog qui ont été écrits au moment de la sortie de Java 7, je ne vois aucun changement de cette chose, donc je me demande quel est le changement et comment cette "fonctionnalité" est appelée ?
Juste une curiosité: en raison du changement, il est possible de déclencher de "faux" déballages:
Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];
Cela compile bien mais donne une exception ClassCastException au moment de l'exécution.
Une référence à ce sujet?
Integer obj = new Integer(2); int x = (int)obj;
: fonctionne sur Java 7, donne une erreur sur Java 6.Réponses:
Il semble que le langage de la section 5.5 Conversion de cast de Java 7 JLS a été mis à jour par rapport à la même section de Java 5/6 JLS , probablement pour clarifier les conversions autorisées.
Java 7 JLS dit
Java 5/6:
Le JLS Java 7 contient également un tableau (tableau 5.1) des conversions autorisées (ce tableau n'est pas inclus dans le JLS Java 5/6) des types de référence aux primitives. Cela répertorie explicitement les transtypages d'objets en primitives comme une conversion de référence restrictive avec unboxing.
La raison est expliquée dans cet e-mail :
la source
Vous avez raison; pour le dire plus simplement:
Cela fonctionne dans Java 7, mais donne une erreur de compilation dans Java 6 et inférieur. Curieusement, cette fonctionnalité n'est pas bien documentée; par exemple, ce n'est pas mentionné ici . Il est discutable s'il s'agit d'une nouvelle fonctionnalité ou d'un correctif de bogue (ou d'un nouveau bogue?), Voir quelques informations et discussions connexes . Le consensus semble indiquer une ambiguïté dans la spécification d'origine, ce qui a conduit à une implémentation légèrement incorrecte / incohérente sur Java 5/6, qui a été corrigée dans 7, car elle était essentielle pour l'implémentation de JSR 292 (Dynamically Typed Languages).
L'autoboxing Java a maintenant quelques pièges et surprises supplémentaires. Par exemple
compilera, mais échouera (avec
ClassCastException
) au moment de l'exécution. Cela fonctionnera à la place:long x = (long)(int)obj;
la source