valueof - java integer max value
¿Por qué las comparaciones== con Integer.valueOf(String) dan resultados diferentes para 127 y 128? (5)
Entero objetos cachés entre -128 y 127 de 256 Entero
No debe comparar referencias de objetos con == o ! = . Deberías usar . es igual (...) en su lugar, o mejor, use la primitiva int en lugar de Integer.
parseInt : analiza el argumento de cadena como un entero decimal con signo. Los caracteres en la cadena deben ser todos dígitos decimales, excepto que el primer carácter puede ser un signo menos ASCII ''-'' (''/ u002D'') para indicar un valor negativo. Se devuelve el valor entero resultante, exactamente como si el argumento y la raíz 10 se dieran como argumentos para el método parseInt (java.lang.String, int).
valueOf Devuelve un objeto entero que contiene el valor extraído de la cadena especificada cuando se analiza con la raíz dada por el segundo argumento. El primer argumento se interpreta como la representación de un entero con signo en el radix especificado por el segundo argumento, exactamente como si los argumentos se hubieran dado al método parseInt (java.lang.String, int). El resultado es un objeto Integer que representa el valor entero especificado por la cadena.
equivalente a
new Integer(Integer.parseInt(s, radix))
radix - la raíz que se utilizará en la interpretación de s
así que si eres igual a Integer.valueOf()
para el entero entremedio
-128 a 127 regresa verdadero en su condición
para lesser than
-128 y greater than
127 da false
No tengo idea de por qué estas líneas de código devuelven valores diferentes:
System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));
El resultado es:
true
false
true
¿Por qué el primero devuelve true
y el segundo devuelve false
? ¿Hay algo diferente que no sé entre 127
y 128
? (Por supuesto que sé que 127
< 128
)
Además, ¿por qué el tercero devuelve true
?
He leído la respuesta a esta pregunta , pero todavía no entiendo cómo puede volverse true
y por qué el código en la segunda línea devuelve false
.
Hay una gran diferencia aquí.
valueOf
está devolviendo un objeto Integer
, que puede tener sus valores almacenados en caché entre -128 y 127. Esta es la razón por la que el primer valor devuelve true
- está en caché - y el segundo valor devuelve false
- 128 no es un valor en caché, por lo que está obteniendo dos instancias de Integer
separadas
Es importante tener en cuenta que está comparando referencias con Integer#valueOf
, y si está comparando un valor que es más grande de lo que admite el caché, no se evaluará como true
, incluso si los valores analizados son equivalentes (por ejemplo: Integer.valueOf(128) == Integer.valueOf(128)
). Debe usar equals()
lugar.
parseInt
está devolviendo una primitiva int
. Esta es la razón por la cual el tercer valor devuelve true
: 128 == 128
es evaluado, y por supuesto, es true
.
Ahora, pasa bastante para que ese tercer resultado sea true
:
Se produce una conversión de unboxing con respecto al operador de equivalencia que está utilizando y los tipos de datos que tiene, a saber,
int
eInteger
. Obtendrá unInteger
devalueOf
en el lado derecho, por supuesto.Después de la conversión, está comparando dos valores
int
prim. La comparación ocurre tal como se esperaría con respecto a las primitivas, por lo que terminas comparando128
y128
.
La clase Integer
tiene una memoria caché estática, que almacena 256 objetos Integer
especiales, uno para cada valor entre -128 y 127. Teniendo esto en cuenta, considere la diferencia entre estos tres.
new Integer(123);
Esto (obviamente) hace un nuevo objeto Integer
.
Integer.parseInt("123");
Esto devuelve un valor de int
primitiva después de analizar el String
.
Integer.valueOf("123");
Esto es más complejo que los demás. Comienza al analizar el String
. Luego, si el valor está entre -128 y 127, devuelve el objeto correspondiente de la memoria caché estática. Si el valor está fuera de este rango, invoca un new Integer()
y pasa el valor para que obtenga un nuevo objeto.
Ahora, considera las tres expresiones en la pregunta.
Integer.valueOf("127")==Integer.valueOf("127");
Esto devuelve verdadero, porque el Integer
cuyo valor es 127 se recupera dos veces de la memoria caché estática, y se compara con sí mismo. Solo hay un objeto Integer
involucrado, por lo que esto devuelve true
.
Integer.valueOf("128")==Integer.valueOf("128");
Esto devuelve false
, porque 128 no está en la caché estática. Por lo tanto, se crea un nuevo Integer
para cada lado de la igualdad. Como hay dos objetos Integer
diferentes, y ==
para los objetos solo devuelve true
si ambos lados son exactamente el mismo objeto, esto va a ser false
.
Integer.parseInt("128")==Integer.valueOf("128");
Esto está comparando el valor int
primitivo 128 a la izquierda, con un objeto Integer
recién creado a la derecha. Pero como no tiene sentido comparar un int
con un Integer
, Java desunirá automáticamente el Integer
antes de hacer la comparación; entonces terminas comparando un int
con un int
. Como la primitiva 128 es igual a sí misma, esto devuelve true
.
Para complementar las respuestas dadas, también tome nota de lo siguiente:
public class Test {
public static void main(String... args) {
Integer a = new Integer(129);
Integer b = new Integer(129);
System.out.println(a == b);
}
}
Este código también se imprimirá: false
Como el usuario Jay ha afirmado en un comentario sobre la respuesta aceptada, se debe tener cuidado al usar operator ==
en los objetos, aquí se está comprobando si ambas referencias son iguales, lo cual no es así, porque son objetos diferentes, aunque representan el mismo valor Para comparar objetos, debe usar el método equals
lugar:
Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));
Esto se imprimirá: true
Puede preguntar: ¿ Pero por qué la primera línea impresa es true
? . Comprobando el código fuente para el método Integer.valueOf
, puede ver lo siguiente:
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Si el param es un número entero entre IntegerCache.low
(predeterminado en -128) y IntegerCache.high
(calculado en tiempo de ejecución con valor mínimo 127), se devuelve un objeto preasignado (en caché). Entonces, cuando usa 127 como parámetro, obtiene dos referencias al mismo objeto almacenado en caché y se vuelve true
en la comparación de las referencias.
Tenga cuidado de devolver los valores de estos métodos. El método valueOf devuelve la instancia Integer:
public static Integer valueOf(int i)
El método parseInt devuelve un valor entero (tipo primitivo):
public static int parseInt(String s) throws NumberFormatException
Explicación para la comparación:
Para ahorrar memoria, dos instancias de los objetos del wrapper siempre serán == cuando sus valores primitivos sean los mismos:
- Booleano
- Byte
- Carácter desde / u0000 hasta / u007f (7f es 127 en decimal)
- Corto y entero de -128 a 127
Cuando == se usa para comparar una primitiva con una envoltura, la envoltura se desenvolverá y la comparación será primitiva a primitiva.
En su situación (de acuerdo con las reglas anteriores):
Integer.valueOf("127")==Integer.valueOf("127")
Esta expresión compara referencias al mismo objeto porque contiene un valor entero entre -128 y 127, por lo que devuelve verdadero.
Integer.valueOf("128")==Integer.valueOf("128")
Esta expresión compara referencias a objetos diferentes porque contienen valores enteros que no están en <-128, 127> por lo que devuelve falso.
Integer.parseInt("128")==Integer.valueOf("128")
Esta expresión compara el valor primitivo (lado izquierdo) y la referencia al objeto (lado derecho), por lo que se desenrollará el lado derecho y su tipo primitivo se comparará con el izquierdo, por lo que devuelve verdadero.