tl; dr, la mia opinione è quella di usare un unario +
per innescare il unboxing su uno degli operandi quando si verifica l'uguaglianza di valore, e semplicemente usare altrimenti gli operatori matematici. La logica segue:
È già stato menzionato che il ==
confronto per Integer
è il confronto di identità, che di solito non è quello che vuole un programmatore, e che l'obiettivo è fare un confronto di valore; tuttavia, ho fatto un po 'di scienza su come eseguire questo confronto in modo più efficiente, sia in termini di compattezza del codice, correttezza e velocità.
Ho usato il solito mazzo di metodi:
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;
}
e ottenuto questo codice dopo la compilazione e la decompilazione:
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;
}
}
Come puoi facilmente vedere, il metodo 1 chiama Integer.equals()
(ovviamente), i metodi 2-4 producono esattamente lo stesso codice , scartando i valori per mezzo di .intValue()
essi e quindi confrontandoli direttamente, e il metodo 5 avvia semplicemente un confronto di identità, essendo il modo errato di confrontare i valori.
Poiché (come già accennato ad esempio da JS) equals()
comporta un overhead (deve essere eseguito instanceof
e un cast non controllato), i metodi 2-4 funzioneranno esattamente con la stessa velocità, notoriamente migliore del metodo 1 se utilizzato in loop stretti, poiché HotSpot non è in grado di ottimizzare i cast e instanceof
.
È abbastanza simile con altri operatori di confronto (ad es. <
/ >
) - innescheranno unboxing, mentre compareTo()
non lo faranno - ma questa volta l'operazione è altamente ottimizzabile da HS poiché intValue()
è solo un metodo migliore (candidato principale per essere ottimizzato).
A mio avviso, la versione 4 usata di rado è il modo più conciso - ogni sviluppatore C / Java esperto sa che il vantaggio unario è nella maggior parte dei casi uguale al cast di int
/ .intValue()
- mentre per alcuni potrebbe essere un piccolo momento WTF (soprattutto quelli che non lo hanno usare un plus unario nella loro vita), mostra probabilmente l'intento in modo più chiaro e più conciso - mostra che vogliamo un int
valore di uno degli operandi, forzando anche l'altro valore a unbox. È anche indiscutibilmente più simile al i1 == i2
confronto regolare usato per i int
valori primitivi .
Il mio voto va per i1 == +i2
e i1 > i2
stile per Integer
gli oggetti, sia per motivi di prestazioni e di coerenza. Inoltre, rende il codice portabile ai primitivi senza cambiare altro che la dichiarazione del tipo. L'uso di metodi denominati mi sembra introdurre rumore semantico, simile allo bigInt.add(10).multiply(-3)
stile molto criticato .