¿Por qué int i = 1024 * 1024 * 1024 * 1024 compilar sin errores?
El límite de int
es de -2147483648 a 2147483647.
Si entro
int i = 2147483648;
Entonces Eclipse pedirá un subrayado rojo bajo "2147483648".
Pero si hago esto:
int i = 1024 * 1024 * 1024 * 1024;
Compilará bien.
public class Test {
public static void main(String[] args) {
int i = 2147483648; // error
int j = 1024 * 1024 * 1024 * 1024; // no error
}
}
Tal vez sea una pregunta básica en Java, pero no tengo idea de por qué la segunda variante no produce ningún error.
5 answers
No hay nada malo con esa declaración; solo estás multiplicando 4 números y asignándolo a un int, simplemente sucede que hay un desbordamiento. Esto es diferente a asignar un único literal , que sería comprobado en tiempo de compilación.
Es el fuera de límites literal que causa el error, no la asignación:
System.out.println(2147483648); // error
System.out.println(2147483647 + 1); // no error
Por el contrario, un long
literal compilaría bien:
System.out.println(2147483648L); // no error
Tenga en cuenta que, de hecho, el resultado es todavía calculado en tiempo de compilación porque 1024 * 1024 * 1024 * 1024
es un expresión constante:
int i = 1024 * 1024 * 1024 * 1024;
Se convierte en:
0: iconst_0
1: istore_1
Observe que el resultado (0
) simplemente se carga y almacena, y no se produce ninguna multiplicación.
De JLS §3.10.1 (gracias a @ChrisK por mencionarlo en los comentarios):
Es un error en tiempo de compilación si un literal decimal de tipo
int
es mayor que2147483648
(231), o si el literal decimal2147483648
aparece en cualquier lugar que no sea como el operando del operador unario menos(§15.15.4).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-14 23:30:44
1024 * 1024 * 1024 * 1024
y 2147483648
no tienen el mismo valor en Java.
En realidad, 2147483648
NI SIQUIERA ES UN VALOR(aunque 2147483648L
lo es) en Java. El compilador literalmente no sabe qué es, o cómo usarlo. Así que se queja.
1024
es un int válido en Java, y un int
válido multiplicado por otro int
válido, es siempre un int
válido. Incluso si no es el mismo valor que esperarías intuitivamente porque el cálculo se desbordará.
Ejemplo
Considere el siguiente ejemplo de código:
public static void main(String[] args) {
int a = 1024;
int b = a * a * a * a;
}
¿Esperarías que esto generara un error de compilación? Se vuelve un poco más resbaladizo ahora.
¿Qué pasa si ponemos un bucle con 3 iteraciones y multiplicamos en el bucle?
El compilador puede optimizar, pero no puede cambiar el comportamiento del programa mientras lo hace.
Algo de información sobre cómo se maneja este caso:
En Java y muchos otros lenguajes, los enteros consistirán en un fijo número de bits. Los cálculos que no encajan en el número dado de bits se desbordarán ; el cálculo se realiza básicamente módulo 2^32 en Java, después de lo cual el valor se convierte de nuevo en un con signo entero.
Otros lenguajes o API usan un número dinámico de bits (BigInteger
en Java), levantan una excepción o establecen el valor a un valor mágico como not-a-number.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 18:13:47
No tengo idea de por qué la segunda variante no produce ningún error.
El comportamiento que sugiere {es decir, la producción de mensaje de diagnóstico cuando un cálculo produce un valor que es mayor que el valor más grande que se puede almacenar en un entero is es una característica . Para que pueda usar cualquier característica, la característica debe ser pensada, considerada como una buena idea, diseñada, especificada, implementada, probada, documentada y enviada a los usuarios.
Para Java, una o más de las cosas en esa lista no sucedió, y por lo tanto no tiene la función. No se cual; tendrías que preguntarle a un diseñador Java.
Para C#, todas esas cosas sucedieron fourteen hace unos catorce años now y así el programa correspondiente en C# ha producido un error desde C# 1.0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-14 18:54:09
Además de la respuesta de arshajii quiero mostrar una cosa más:
No es la asignación la que causa el error, sino simplemente el uso del literal. Cuando intentes
long i = 2147483648;
Notarás que también causa un error de compilación ya que el lado derecho sigue siendo un int
-literal y fuera de rango.
Así que las operaciones con int
-valores (y eso incluye las asignaciones) pueden desbordarse sin un error de compilación (y sin un error de tiempo de ejecución también), pero el compilador simplemente no puede manejar esos literales demasiado grandes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-12 22:45:52
R:, Porque no es un error.
Fondo: La multiplicación 1024 * 1024 * 1024 * 1024
conducirá a un desbordamiento. Un desbordamiento es muy a menudo un error. Diferentes lenguajes de programación producen un comportamiento diferente cuando ocurren desbordamientos. Por ejemplo, C y C++ lo llaman "comportamiento indefinido" para enteros con signo, y el comportamiento se define como enteros sin signo (tome el resultado matemático, agregue UINT_MAX + 1
siempre que el resultado sea negativo, resta UINT_MAX + 1
siempre que el resultado sea mayor que UINT_MAX
).
En el caso de Java, si el resultado de una operación con valores int
no está en el rango permitido, conceptualmente Java suma o resta 2^32 hasta que el resultado está en el rango permitido. Así que la declaración es completamente legal y no en error. Simplemente no produce el resultado que puede haber esperado.
Seguramente puede argumentar si este comportamiento es útil, y si el compilador debe darle una advertencia. Yo diría personalmente que una advertencia sería muy útil, pero un error sería incorrecto ya que es Java legal.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 09:06:08