java operator-keyword autoboxing ternary

Autoboxing de Java y locura del operador ternario.



operator-keyword ternary (4)

Bueno, Integer.valueOf(String) devuelve un Integer y -1 es un int primitivo. El primer ejemplo es forzado a unbox porque un término es primitivo. También podrías haber usado

Integer boxedRsrq = boxedPci != null ? rsrqs.get(boxedPci.toString()) : (Integer) -1;

Lo que habría encajonado el -1.

Acabo de pasar un par de horas frustrantes depurando este código:

LinkedHashMap<String, Integer> rsrqs = new LinkedHashMap<String, Integer>(); Integer boxedPci = 52; Integer boxedRsrq = boxedPci != null ? rsrqs.get(boxedPci.toString()) : -1;

Lo anterior produce una NullPointerException. El siguiente código no lo hace:

LinkedHashMap<String, Integer> rsrqs = new LinkedHashMap<String, Integer>(); Integer boxedPci = 52; Integer boxedRsrq = boxedPci != null ? rsrqs.get(boxedPci.toString()) : Integer.valueOf(-1);

La única diferencia es envolver el -1 con Integer.valueOf (). Estoy seguro de que voy a golpearme la frente una vez que alguien explique por qué este código se comporta de la manera en que lo hace ... pero, ¿puede alguien explicarme por qué este código se comporta de la manera que lo hace :)?

- editar

Pensándolo bien, sospecho que el NPE viene de rsrqs.get () devolviendo nulo, lo que creo que Java está intentando desempaquetar en un int, antes de volver a un entero. Integer.valueOf () obliga a Java a realizar el paso de unbox-box. Moraleja de la historia; no ignore esas advertencias de boxeo en Eclipse;)


La explicación puede concluirse a partir de la información en la especificación del lenguaje java: 15.25. ¿Operador condicional? : .

De la tabla de allí, obtiene la información de que, si el segundo operando ( rsrqs.get(boxedPci.toString()) ) es de tipo Integer y el tercer operando es de tipo int , el resultado será de tipo int .

Eso sin embargo significa que

Integer boxedRsrq = boxedPci != null ? rsrqs.get(boxedPci.toString()) : -1;

es semánticamente lo mismo que

Integer boxedRsrq = boxedPci != null ? ((int)rsrqs.get(boxedPci.toString())) : -1;

Pero eso significa que obtienes una NullPointerException , si obtienes un null del mapa, lo que obviamente sucede.

Si convierte el tercer operando en Integer , el segundo operando nunca se convertirá en int y no ocurre NPE.


Las expresiones ternarias, como cualquier expresión, tienen un tipo determinado por el compilador. Si los dos lados de la expresión ternaria tienen lo que parecen tipos diferentes, entonces el compilador intentará encontrar un tipo base común utilizando la menos ambigua de las dos opciones. En su caso, el -1 es el menos ambiguo, por lo que el tipo de expresión ternaria es int . Lamentablemente, el compilador no usa la inferencia de tipos basada en la variable de recepción.

La expresión rsrqs.get(boxedPci.toString()) luego se evalúa y se fuerza en el tipo int para que coincida con la expresión ternaria, pero como es null , arroja el NPE.

Al encajonar el -1 , el valor de la expresión ternaria es Integer , por lo que está a salvo de nulos.


1

es un int, no un entero. Entonces, Java va a desmarcar su Integer a int, lo que causa la excepción NullPointerException. Cuando auto-unbox un entero nulo, se traduce en una NullPointerException. ( referencia aquí )

Pero cuando usas

Integer.valueOf(-1)

no es necesario que lo desmarque automáticamente, lo que no conlleva excepciones.