He notado una diferencia en el comportamiento de desempaquetado automático entre Java SE 6 y Java SE 7. Me pregunto por qué es así, porque no puedo encontrar ninguna documentación de cambios en este comportamiento entre estas dos versiones.
He aquí un ejemplo sencillo:
Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Esto se compila bien con javac de Java SE 7. Sin embargo, si le doy al compilador el argumento "-source 1.6", aparece un error en la última línea:
inconvertible types
found : java.lang.Object
required: int
Intenté descargar Java SE 6 para compilarlo con el compilador nativo de la versión 6 (sin ninguna opción de fuente). Está de acuerdo y da el mismo error que el anterior.
Entonces, ¿qué da? A partir de un poco más de experimentación, parece que el unboxing en Java 6 solo puede desempaquetar valores que claramente (en el momento de la compilación) son del tipo encuadrado. Por ejemplo, esto funciona en ambas versiones:
Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Entonces, parece que entre Java 6 y 7, la función de desempaquetado se mejoró para que pudiera lanzar y desempaquetar tipos de objetos de una sola vez, sin saber (en el momento de la compilación) que el valor es del tipo de caja correcto. Sin embargo, al leer la Especificación del lenguaje Java o las publicaciones de blogs que se escribieron en el momento en que salió Java 7, no veo ningún cambio en esto, así que me pregunto cuál es el cambio y cómo se llama esta "característica". ?
Solo una curiosidad: Debido al cambio, es posible desencadenar unboxings "incorrectos":
Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];
Esto se compila bien pero da una ClassCastException en tiempo de ejecución.
¿Alguna referencia sobre esto?
Integer obj = new Integer(2); int x = (int)obj;
: funciona en Java 7, da error en Java 6.Respuestas:
Parece que el lenguaje de la sección 5.5 Conversión de conversión de Java 7 JLS se actualizó en comparación con la misma sección en Java 5/6 JLS , probablemente para aclarar las conversiones permitidas.
Java 7 JLS dice
Java 5/6:
Java 7 JLS también contiene una tabla (tabla 5.1) de conversiones permitidas (esta tabla no está incluida en Java 5/6 JLS) de tipos de referencia a primitivas. Esto enumera explícitamente las conversiones de Object a primitivas como una conversión de referencia restringida con unboxing.
El motivo se explica en este correo electrónico :
fuente
Tienes razón; para decirlo más simplemente:
Esto funciona en Java 7, pero da un error de compilación en Java 6 y versiones anteriores. Curiosamente, esta característica no está documentada de forma destacada; por ejemplo, no se menciona aquí . Es discutible si se trata de una nueva función o una corrección de errores (¿o un nuevo error?), Consulte información y discusión relacionada . El consenso parece apuntar a una ambigüedad en la especificación original, lo que llevó a una implementación ligeramente incorrecta / inconsistente en Java 5/6, que se corrigió en 7, porque era fundamental para la implementación de JSR 292 (lenguajes dinámicamente tipados).
El autoboxing de Java tiene ahora más trampas y sorpresas. Por ejemplo
se compilará, pero fallará (con
ClassCastException
) en tiempo de ejecución. Esto, en cambio, funcionará:long x = (long)(int)obj;
fuente