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 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 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:
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 obtuve este 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 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 valores
Dado que (como ya se mencionó, por ejemplo, JS) equals()
incurre en una sobrecarga (tiene que hacer instanceof
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, mientras compareTo()
que no lo harán, pero esta vez, la operación es altamente optimizable por HS ya que intValue()
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 un int
valor de uno de los operandos, lo que obliga al otro valor a desempaquetar también. También es indiscutiblemente más similar a la i1 == i2
comparación regular utilizada para int
valores primitivos .
Mi voto va para i1 == +i2
y i1 > i2
estilo para Integer
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 al bigInt.add(10).multiply(-3)
estilo muy criticado .