Diferencias en el auto-unboxing entre Java 6 vs Java 7
casting java-7 (2)
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
Una expresión de un tipo de referencia puede experimentar una conversión de conversión a un tipo primitivo sin error, mediante la conversión de unboxing.
Java 5/6:
Un valor de un tipo de referencia puede convertirse a un tipo primitivo mediante la conversión de unboxing (§5.1.8).
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 primitivos. Esto enumera explícitamente los moldes de Object a primitivos como una conversión de referencia de estrechamiento con unboxing.
El motivo se explica en este correo electrónico :
En resumen: si la especificación. permite (Objeto) (int) también debe permitir (int) (Objeto).
He notado una diferencia en el comportamiento de unboxing 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.
Aquí hay un ejemplo simple:
Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Esto 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
Traté de descargar Java SE 6 para compilar con el compilador nativo de la versión 6 (sin ninguna opción de fuente). Acepta y da el mismo error que el anterior.
Entonces, ¿qué da? A partir de un poco más de experimentación, parece que el desempaquetado en Java 6 solo puede desunir los valores que claramente (en tiempo de compilación) son del tipo de recuadro. Por ejemplo, esto funciona en ambas versiones:
Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Así que parece que entre Java 6 y 7, la característica de unboxing se mejoró para que pudiera lanzar y desempaquetar tipos de objetos en un solo golpe, sin saber (en tiempo de compilación) que el valor es del tipo apropiado. Sin embargo, al leer la Especificación del lenguaje Java o las publicaciones en el blog que se escribieron en el momento en que apareció Java 7, no veo ningún cambio en esto, así que me pregunto cuál es el cambio y cómo se llama esta "función" ?
Solo una curiosidad: debido al cambio, es posible activar unboxings "incorrectos":
Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];
Esto compila bien, pero da una ClassCastException en tiempo de ejecución.
Cualquier referencia sobre esto?
Tienes razón; para decirlo más simple:
Object o = new Integer(1234);
int x = (int) o;
Esto funciona en Java 7, pero da un error de compilación en Java 6 y siguientes. Extrañamente, esta característica no está documentada de manera prominente; por ejemplo, no se menciona here . Es discutible si se trata de una nueva característica o una corrección de errores (¿o un nuevo error?), Vea alguna información relacionada y discusión . El consenso parece apuntar a una ambigüedad en la especificación original, que condujo 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 de tipo dinámico).
El autoboxing de Java ahora tiene más trampas y sorpresas. Por ejemplo
Object obj = new Integer(1234);
long x = (long)obj;
compilará, pero fallará (con ClassCastException
) en tiempo de ejecución. Esto, en cambio, funcionará:
long x = (long)(int)obj;