Por qué hacer = = comparaciones con Integer.valueOf (Cadena) ¿da resultados diferentes para 127 y 128?


No tengo idea de por qué estas líneas de código devuelven diferentes valores:

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"));

La salida es:

true
false
true

¿por Qué la primera vuelta true y el segundo retorno false? ¿Hay algo diferente que no sepa entre 127 y 128? (Por supuesto que sé que 127 128.)

También, ¿por qué el tercero regresa true?

He leído la respuesta de esta pregunta , pero todavía no entiendo cómo puede regresar true, y por qué el código en la segunda línea devuelve false.

Author: Community, 2014-01-02

5 answers

Hay una diferencia sorprendente aquí.

valueOf devuelve 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á almacenado en caché - y el segundo valor devuelve false - 128 no es un valor almacenado en caché, por lo que obtendrá dos instancias 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 que lo que admite la caché, lo hará no evaluar a true, incluso si los valores analizados son equivalentes (caso en punto: Integer.valueOf(128) == Integer.valueOf(128)). Usted debe usar equals() en su lugar.

parseInt está devolviendo un primitivo int. Esta es la razón por la que el tercer valor devuelve true - 128 == 128 se evalúa, y es por supuesto, true.

Ahora, un poco justo sucede para hacer ese tercer resultado true:

  • Se produce una conversión de unboxing con respecto al operador de equivalencia que está utilizando y los tipos de datos que tener-a saber, int y Integer. Usted está recibiendo un Integer de valueOf en el lado derecho, por supuesto.

  • Después de la conversión, estás comparando dos valores primitivos int. La comparación ocurre tal y como esperarías con respecto a las primitivas, por lo que terminas comparando 128 y 128.

 186
Author: Makoto,
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-01-02 22:49:55

La clase Integer tiene una caché estática, que almacena 256 objetos Integer especiales - uno por cada valor entre -128 y 127. Con eso en mente, considere la diferencia entre estos tres.

new Integer(123);

Esto (obviamente) hace un nuevo objeto Integer.

Integer.parseInt("123");

Esto devuelve un valor primitivo int después de analizar el String.

Integer.valueOf("123");

Esto es más complejo que los otros. Comienza por analizar el String. Entonces, si el valor está entre -128 y 127, devuelve el objeto correspondiente de la caché estática. Si el valor está fuera de este rango, entonces invoca new Integer() y pasa el valor, para que obtenga un nuevo objeto.

Ahora, consideremos las tres expresiones de la pregunta.

Integer.valueOf("127")==Integer.valueOf("127");

Esto devuelve true, porque el Integer cuyo valor es 127 se recupera dos veces de la caché estática, y se compara consigo mismo. Solo hay un objeto Integer involucrado, por lo que devuelve true.

Integer.valueOf("128")==Integer.valueOf("128");

Esto devuelve false, porque 128 no es en la caché estática. Así se crea un nuevo Integer para cada lado de la igualdad. Dado que hay dos objetos Integer diferentes, y == for objects solo devuelve true si ambos lados son exactamente el mismo objeto, esto va a ser false.

Integer.parseInt("128")==Integer.valueOf("128");

Esto es comparar el valor primitivo int 128 a la izquierda, con un objeto recién creado Integer a la derecha. Pero debido a que no tiene sentido comparar un int con un Integer, Java descomprimirá automáticamente el Integer antes de hacer la comparación; así terminas comparando un int un int. Dado que el primitivo 128 es igual a sí mismo, esto devuelve true.

 120
Author: Dawood ibn Kareem,
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-01-02 06:32:25

Tenga cuidado de devolver los valores de estos métodos. El método valueOf devuelve la instancia entera:

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:

Con el fin de ahorrar memoria, dos instancias de la wrapper objects, will always be = = when their valores primitivos son los mismos:

  • Booleano
  • Byte
  • Carácter de \u0000 a \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 será sin envolver 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 true.

Integer.valueOf("128")==Integer.valueOf("128")

Esta expresión compara las referencias a diferentes objetos porque contienen valores enteros no en por lo que devuelve false.

Integer.parseInt("128")==Integer.valueOf("128")

Esta expresión compara el valor primitivo (lado izquierdo) y la referencia al objeto (lado derecho) así que el lado derecho se desenvolverá y su tipo primitivo se comparará con el izquierdo para que devuelva true.

 13
Author: piobab,
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-01-02 11:01:14

Para complementar las respuestas dadas, también tome nota de lo siguiente: {[13]]}

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 reclamado en un comentario la respuesta aceptada, hay que tener cuidado al usar el operador == en objetos, aquí estás comprobando si ambas referencias son iguales, que no lo es, 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

Usted puede preguntar, Pero entonces ¿por qué la primera línea impresa 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 parámetro es un entero entre IntegerCache.low (predeterminado a -128) y IntegerCache.high (calculado en tiempo de ejecución con un valor mínimo 127), se devuelve un objeto preasignado (almacenado en caché). Así que cuando usas 127 como parámetro, obtienes dos referencias al mismo objeto almacenado en caché y obtienes true en la comparación de las referencias.

 6
Author: higuaro,
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
2017-05-23 10:31:12

Objetos enteros cachés entre -128 y 127 de 256 Entero

No debe comparar referencias de objetos con == ¡o !=. Deberías usarlo .es igual a(..) en su lugar, o mejor - use el int primitivo en lugar de Entero.

ParseInt : Analiza el argumento string como un entero decimal con signo. Los caracteres de la cadena deben ser todos dígitos decimales, excepto que el primer carácter puede ser un signo menos ASCII ' - ' ('\u002D') para indicar un negativo valor. El valor entero resultante se devuelve, exactamente como si el argumento y la base 10 se dieran como argumentos al parseInt (java.lang.String, int) método.

Valor de 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 la raíz especificada por el segundo argumento, exactamente como si los argumentos parseInt (java.lang.String, int) método. El resultado es un objeto Entero que representa el valor entero especificado por la cadena.

Equivalente a

new Integer(Integer.parseInt(s, radix))

Radix - la radix que debe utilizarse en la interpretación de s

Así que si es igual Integer.valueOf() para el entero inbetween

-128 a 127 devuelve true en su condición

Para lesser than -128 y greater than 127 da false

 5
Author: Nambi,
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-01-02 15:41:06