tl; dr mi opinión es usar un unario +
para disparar el unboxing en uno de los operandos en la comprobación de la igualdad de valor, y simplemente utilizar los operadores matemáticos lo contrario. Rationale follows:
Ya se ha mencionado que la comparación ==
para Integer
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 science sobre cómo hacer esa comparación más eficientemente, tanto en términos de compacidad, corrección y velocidad del código.
He utilizado el grupo habitual de métodos:
public boolean method1() {
Integer i1 = 7, i2 = 5;
return i1.equals(i2);
}
public boolean method2() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2.intValue();
}
public boolean method3() {
Integer i1 = 7, i2 = 5;
return i1.intValue() == i2;
}
public boolean method4() {
Integer i1 = 7, i2 = 5;
return i1 == +i2;
}
public boolean method5() { // obviously not what we want..
Integer i1 = 7, i2 = 5;
return i1 == i2;
}
y tiene el código después de la compilación y descompilación:
public boolean method1() {
Integer var1 = Integer.valueOf(7);
Integer var2 = Integer.valueOf(5);
return var1.equals(var2);
}
public boolean method2() {
Integer var1 = Integer.valueOf(7);
Integer var2 = Integer.valueOf(5);
if (var2.intValue() == var1.intValue()) {
return true;
} else {
return false;
}
}
public boolean method3() {
Integer var1 = Integer.valueOf(7);
Integer var2 = Integer.valueOf(5);
if (var2.intValue() == var1.intValue()) {
return true;
} else {
return false;
}
}
public boolean method4() {
Integer var1 = Integer.valueOf(7);
Integer var2 = Integer.valueOf(5);
if (var2.intValue() == var1.intValue()) {
return true;
} else {
return false;
}
}
public boolean method5() {
Integer var1 = Integer.valueOf(7);
Integer var2 = Integer.valueOf(5);
if (var2 == var1) {
return true;
} else {
return false;
}
}
Como se puede ver fácilmente, el método 1 llamadas Integer.equals()
(obviamente), métodos 2-4 da como resultado exactamente el mismo código, desenvuelve los valores por medio de .intValue()
y luego los compara directamente, y el método 5 simplemente desencadena una comparación de identidad, siendo la forma incorrecta de comparar valores.
Puesto que (como ya se ha mencionado por ejemplo, JS) equals()
incurre en una sobrecarga (que tiene que ver instanceof
y un reparto sin marcar), los métodos de 2-4 trabajarán con exactamente la misma velocidad, noticingly mejor que el método 1 cuando se utiliza en apretado bucles, ya que HotSpot no es probable que optimice los moldes & instanceof
.
es bastante similar con otros operadores de comparación (por ejemplo <
/>
) - van a desencadenar unboxing, durante el uso de compareTo()
no - pero esta vez, la operación es altamente optimizable por HS desde intValue()
es sólo un método getter (primer candidato a ser optimizado).
En mi opinión, la versión rara vez se utilizan 4 es la forma más concisa - cada C sazonada/desarrollador de Java sabe que más unario es en la mayoría de los casos igual a emitir a int
/.intValue()
- si bien puede ser un poco WTF momento para algunos (principalmente aquellos que no usaron el plus único durante su vida útil), se puede decir que muestra el intento más claro y más lacónico - muestra que queremos un valor int
de uno de los operandos, forzando el otro valor a unbox como bien. También es indiscutiblemente más similar a la comparación i1 == i2
normal utilizada para los valores primitivos int
.
Mi voto va para i1 == +i2
estilo & i1 > i2
para Integer
objetos, tanto por razones de rendimiento & 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. El uso de métodos con nombre me parece una introducción de ruido semántico, similar al muy criticado bigInt.add(10).multiply(-3)
estilo.
Bueno, lo que pasó cuando se trató? ¿Qué observaste? –
@Bart Kiers: un experimento explícito solo podría desmentir, no demostrar que se produce unboxing. Si se usa '==' en lugar de 'igual', se obtiene el resultado correcto, puede deberse a que los números encapsulados 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 lo que parece estar sucediendo. (Al menos, es por eso que estoy aquí.) –