Sé que si compara un entero primitivo en caja con una constante como:
Integer a = 4;
if (a < 5)
a
se desempaquetará automáticamente y la comparación funcionará.
Sin embargo, ¿qué sucede cuando compara dos recuadros Integers
y desea comparar igualdad o menor que / mayor que?
Integer a = 4;
Integer b = 5;
if (a == b)
¿El código anterior resultará en una comprobación para ver si son el mismo objeto, o se desempaquetará automáticamente en ese caso?
Qué pasa:
Integer a = 4;
Integer b = 5;
if (a < b)
?
java
integer
autoboxing
shmosel
fuente
fuente
==
lugar deequals
arroja el resultado correcto, puede deberse a que los números en caja están siendo internados o reutilizados (como una optimización del compilador, presumiblemente). La razón para hacer esta pregunta es descubrir qué está sucediendo internamente, no qué parece estar sucediendo. (Al menos, por eso estoy aquí.)Respuestas:
No, == entre Entero, Largo, etc. verificará la igualdad de referencia , es decir
esta comprobará si
x
yy
referirse al mismo objeto en lugar de la igualdad de objetos.Entonces
Está garantizado para imprimir
false
. La internación de valores "pequeños" autoboxed puede conducir a resultados difíciles:Esto se imprimirá
true
, debido a las reglas del boxeo ( JLS sección 5.1.7 ). Todavía se usa la igualdad de referencia, pero las referencias son realmente iguales.Personalmente usaría:
o
Como usted dice, para cualquier comparación entre un tipo de contenedor (
Integer
,Long
etc.) y un tipo numérico (int
,long
etc.) el valor del tipo de contenedor es caja y la prueba se aplica a los valores primitivos involucrados.Esto ocurre como parte de la promoción numérica binaria ( JLS sección 5.6.2 ). Mire la documentación de cada operador individual para ver si se aplica. Por ejemplo, de los documentos para
==
y!=
( JLS 15.21.1 ):y para
<
,<=
,>
y>=
( JLS 15.20.1 )Tenga en cuenta que nada de esto se considera parte de la situación en la que ninguno de los dos tipos es numérico.
fuente
x.compareTo(y) < 0
lugar dex < y
?==
aún probará la igualdad de objetos. Sin embargo, es fácil dejarse engañar:Sus ejemplos con desigualdades funcionarán ya que no están definidos en Objetos. Sin embargo, con la
==
comparación, la igualdad de objetos aún se verificará. En este caso, cuando inicializa los objetos desde una primitiva en caja, se utiliza el mismo objeto (tanto para a como para b). Esta es una optimización correcta ya que las clases de caja primitivas son inmutables.fuente
200
, se imprimirán ambas pruebasfalse
.equals
ser llamado".Desde Java 1.7 puede usar Objects.equals :
fuente
==
comprueba la igualdad de referencia, sin embargo, al escribir código como:Java es lo suficientemente inteligente como para reutilizar el mismo inmutable para
a
yb
, así que esto es cierto:a == b
. Curioso, escribí un pequeño ejemplo para mostrar dónde Java deja de optimizar de esta manera:Cuando compilo y ejecuto esto (en mi máquina), obtengo:
fuente
tl; dr, mi opinión es usar un unario
+
para activar el desempaquetado en uno de los operandos al verificar la igualdad de valores, y simplemente usar los operadores matemáticos de lo contrario. La justificación sigue:Ya se ha mencionado que la
==
comparación paraInteger
es una comparación de identidad, que generalmente no es lo que un programador quiere, y que el objetivo es hacer una comparación de valores; Aún así, he hecho un poco de ciencia sobre cómo hacer esa comparación de manera más eficiente, tanto en términos de compacidad, corrección y velocidad del código.Usé los métodos habituales:
y obtuve este código después de la compilación y descompilación:
Como puede ver fácilmente, el método 1 llama
Integer.equals()
(obviamente), los métodos 2-4 dan como resultado exactamente el mismo código , desenvolviendo los valores mediante.intValue()
y luego comparándolos directamente, y el método 5 simplemente desencadena una comparación de identidad, siendo la forma incorrecta de comparar valoresDado que (como ya se mencionó, por ejemplo, JS)
equals()
incurre en una sobrecarga (tiene que hacerinstanceof
y un lanzamiento no verificado), los métodos 2-4 funcionarán con exactamente la misma velocidad, notoriamente mejor que el método 1 cuando se usa en bucles estrechos, ya que HotSpot no es probable optimizar los moldes &instanceof
.Es bastante similar con otros operadores de comparación (por ejemplo,
<
/>
): activarán el desempaquetado, mientrascompareTo()
que no lo harán, pero esta vez, la operación es altamente optimizable por HS ya queintValue()
es solo un método getter (candidato principal para ser optimizado).En mi opinión, la versión 4 que rara vez se utiliza es la forma más concisa: cada desarrollador experimentado de C / Java sabe que unary plus es en la mayoría de los casos igual a emitir a
int
/.intValue()
, mientras que puede ser un pequeño momento WTF para algunos (principalmente aquellos que no lo hicieron) no use unary plus en su vida), posiblemente muestre la intención de la manera más clara y clara: muestra que queremos unint
valor de uno de los operandos, lo que obliga al otro valor a desempaquetar también. También es indiscutiblemente más similar a lai1 == i2
comparación regular utilizada paraint
valores primitivos .Mi voto va para
i1 == +i2
yi1 > i2
estilo paraInteger
los objetos, tanto por razones de rendimiento y consistencia. También hace que el código sea portátil para las primitivas sin cambiar nada más que la declaración de tipo. Usar métodos con nombre me parece introducir ruido semántico, similar albigInt.add(10).multiply(-3)
estilo muy criticado .fuente
unary +
(unary plus), ver por ejemplo stackoverflow.com/questions/2624410/…Vocación
Funcionará la mayor parte del tiempo, pero no está garantizado que siempre funcione, así que no lo use.
La forma más adecuada de comparar dos clases de enteros para la igualdad, suponiendo que se denominen 'a' y 'b' es llamar:
También puede usar esta forma, que es un poco más rápida.
En mi máquina, 99 mil millones de operaciones tomaron 47 segundos usando el primer método y 46 segundos usando el segundo método. Tendría que comparar miles de millones de valores para ver cualquier diferencia.
Tenga en cuenta que 'a' puede ser nulo ya que es un objeto. Comparar de esta manera no causará una excepción de puntero nulo.
Para comparar mayor y menor que, use
fuente
if (a==b)
funciona solo para valores pequeños y no funcionará la mayoría de las veces.Siempre debemos utilizar el método equals () para comparar dos enteros. Es la práctica recomendada.
Si comparamos dos enteros usando == eso funcionaría para cierto rango de valores enteros (Entero de -128 a 127) debido a la optimización interna de JVM.
Por favor vea ejemplos:
Caso 1:
En el caso anterior, JVM usa el valor de a y b del grupo en caché y devuelve la misma instancia de objeto (por lo tanto, la dirección de memoria) del objeto entero y obtenemos que ambos son iguales. Su optimización JVM lo hace para ciertos valores de rango.
Caso 2: en este caso, ayb no son iguales porque no viene con el rango de -128 a 127.
Forma apropiada:
Espero que esto ayude.
fuente
En mi caso, tuve que comparar dos
Integer
s para la igualdad donde ambos podrían estarnull
. Busqué un tema similar, no encontré nada elegante para esto. Se le ocurrió una sencilla utilidad de funciones.fuente
Debido a que el método de comparación debe hacerse en base al tipo int (x == y) o la clase Integer (x.equals (y)) con el operador correcto
fuente
este método compara dos números enteros con verificación nula, ver pruebas
fuente
Objects.equals(x,y)
método en lugar de usar el tuyo.