137 votes

Booléens, opérateurs conditionnels et autoboxing

Pourquoi ce lancer``

alors que ce n’est pas

?

La solution est d’ailleurs de remplacer par pour éviter les être unboxed pour --qui n’est pas possible. Mais ce n’est pas la question. La question est pourquoi? Y a-t-il des références JLS qui confirme ce comportement, en particulier de l’affaire 2e ?

96voto

Bert F Points 27237

La différence est que le type explicite de l' returnsNull() méthode affecte le typage des expressions au moment de la compilation:

E1: `true ? returnsNull() : false` - boolean (auto-unboxing 2nd operand to boolean)

E2: `true ? null : false` - Boolean (autoboxing of 3rd operand to Boolean)

Voir Java Language Specification, section de 15,25 Opérateur Conditionnel ? :

  • Pour E1, les types de la 2e et 3e opérandes sont Boolean et boolean , respectivement, de sorte que cette clause s'applique:

    Si l'un des deuxième et troisième opérandes est de type booléen et le type de l'autre est de type Booléen, alors le type de l'expression conditionnelle est un booléen.

    Puisque le type de l'expression est - boolean, le 2ème opérande doit être contraints d' boolean. Le compilateur insère auto-unboxing code de la 2ème opérande (valeur de retour de l' returnsNull()) pour le type d' boolean. Bien sûr, cela provoque le NPE de l' null retourné au moment de l'exécution.

  • Pour E2, les types de la 2e et 3e opérandes sont <special null type> (pas Boolean comme dans E1!) et boolean respectivement, donc, pas spécifique à taper clause s'applique (allez le lire!), donc au final "autrement" clause s'applique:

    Sinon, la deuxième et la troisième opérandes sont de types S1 et S2 respectivement. Laissez-T1 être le type qui résulte de l'application de la boxe de conversion à S1, et laissez-T2 être le type qui résulte de l'application de la boxe de conversion à S2. Le type de l'expression conditionnelle est le résultat de l'application de capture de conversion (§5.1.10) lub(T1, T2) (§15.12.2.7).

    • S1 == <special null type> (voir §4.1)
    • S2 == boolean
    • T1 == case(S1) == <special null type> (voir le dernier élément de la liste de boxe conversions dans les §5.1.7)
    • T2 == case(S2) == `Boolean
    • lub(T1, T2) == Boolean

    Donc, le type de l'expression conditionnelle est - Boolean et le 3ème opérande doit être contraints d' Boolean. Le compilateur insère auto-boxing code pour la 3ème opérande (false). La 2ème opérande n'a pas besoin de l'auto-unboxing comme en E1, donc pas d'auto-unboxing NPE lorsqu' null est retourné.


Cette question a besoin d'un type similaire à l'analyse:

Java opérateur conditionnel ?: type de résultat

29voto

jjungnickel Points 515

La ligne:

    Boolean b = true ? returnsNull() : false;

est transformée en interne:

    Boolean b = true ? returnsNull().getBoolean() : false; 

pour effectuer l'unboxing; ainsi: null.getBoolean() donnera un NPE

C'est l'un des principaux écueils lors de l'utilisation de l'autoboxing. Ce comportement est en effet documenté dans 5.1.8 JLS

Edit: je crois que l'unboxing est due à la troisième opérateur de type booléen, comme (cast implicite ajouté):

   Boolean b = (Boolean) true ? true : false; 

17voto

axtavt Points 126632

À partir de Java Language Specification, section 15.25:

  • Si l'un des deuxième et troisième opérandes est de type booléen et le type de l'autre est de type Booléen, alors le type de la condition l'expression est de type boolean.

Ainsi, le premier exemple tente de l'appeler Boolean.booleanValue() afin de convertir Boolean de boolean selon la première règle.

Dans le second cas, le premier opérande est de type null, quand le second n'est pas du type de référence, de sorte que l'autoboxing de conversion est appliqué:

  • Sinon, la deuxième et de la troisième les opérandes sont de types S1 et S2 respectivement. Laissez-T1 être le type de les résultats de l'application de la boxe la conversion à S1, et laissez-T2 être le le type qui résulte de l'application de la boxe la conversion à S2. Le type de la expression conditionnelle est le résultat de l'application de capture de conversion (§5.1.10) lub(T1, T2) (§15.12.2.7).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X