Comportamiento variable por posible pérdida de precisión

En Java, cuando lo haces

int b = 0; b = b + 1.0; 

Obtiene una posible pérdida de error de precisión. Pero ¿por qué es que si lo haces

 int b = 0; b += 1.0; 

No hay ningún error?

Eso es porque b += 1.0; es equivalente a b = (int) ((b) + (1.0)); . La conversión primitiva de estrechamiento (JLS 5.1.3) está oculta en la operación de asignación compuesta.

JLS 15.26.2 Operadores de asignación de compuestos (JLS Tercera edición):

Una expresión de asignación compuesta de la forma E1 op = E2 es equivalente a E1 = (T) ((E1) op (E2)) , donde T es el tipo de E1 , excepto que E1 se evalúa solo una vez.

Por ejemplo, el siguiente código es correcto:

 short x = 3; x += 4.6; 

y resulta en x tiene el valor 7 porque es equivalente a:

 short x = 3; x = (short)(x + 4.6); 

Esto también explica por qué se comstack el siguiente código:

 byte b = 1; int x = 5; b += x; // compiles fine! 

Pero esto no:

 byte b = 1; int x = 5; b = b + x; // DOESN'T COMPILE! 

Necesitas lanzar explícitamente en este caso:

 byte b = 1; int x = 5; b = (byte) (b + x); // now it compiles fine! 

Vale la pena señalar que el elenco implícito en las asignaciones compuestas es el tema de Puzzle 9: Tweedledum del maravilloso libro Java Puzzlers . Aquí hay algunos extractos del libro (ligeramente editados por brevedad):

Muchos progtwigdores piensan que x += i; es simplemente una abreviatura de x = x + i; . Esto no es del todo cierto: si el tipo de resultado es más ancho que el de la variable, el operador de asignación compuesta realiza una conversión de primitiva de estrechamiento silencioso.

Para evitar sorpresas desagradables, no utilice operadores de asignación compuesta en variables de tipo byte , short o char . Al utilizar operadores de asignación compuesta en variables de tipo int , asegúrese de que la expresión en el lado derecho no sea de tipo long , float o double . Al usar operadores de asignación compuesta en variables del tipo float , asegúrese de que la expresión en el lado derecho no sea de tipo double . Estas reglas son suficientes para evitar que el comstackdor genere lances de estrechamiento peligrosos.

Para los diseñadores de idiomas, probablemente sea un error para los operadores de asignación compuesta generar conversiones invisibles; las asignaciones compuestas donde la variable tiene un tipo más estrecho que el resultado del cálculo probablemente sean ilegales.

Vale la pena señalar el último párrafo: C # es mucho más estricto a este respecto (consulte la especificación del lenguaje C # 7.13.2 Asignación compuesta ).

Intereting Posts