tl; dr moim zdaniem jest użycie jedności +
do uruchomienia rozpakowywania na jednym z operandów podczas sprawdzania równości wartości, a po prostu użycie operatorów matematycznych w przeciwnym razie. Uzasadnienie jest następujące:
Wspomniano już, że ==
porównanie Integer
to porównanie tożsamości, które zwykle nie jest tym, czego chce programista, a celem jest porównanie wartości; Mimo to zrobiłem trochę nauki o tym, jak zrobić to porównanie najbardziej wydajnie, zarówno pod względem zwięzłości kodu, poprawności i szybkości.
Użyłem zwykłej wiązki metod:
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;
}
i otrzymałem ten kod po kompilacji i dekompilacji:
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;
}
}
Jak łatwo zauważyć, wywołania metody 1 Integer.equals()
(oczywiście), metody 2-4 dają dokładnie ten sam kod , rozpakowywanie wartości za pomocą, .intValue()
a następnie bezpośrednie porównywanie, a metoda 5 po prostu uruchamia porównanie tożsamości, ponieważ jest to niewłaściwy sposób porównaj wartości.
Ponieważ (jak już wspomniano np. JS) equals()
powoduje narzut (musi to zrobić instanceof
i niezaznaczone rzutowanie), metody 2-4 będą działały z dokładnie taką samą prędkością, zauważalnie lepszą niż metoda 1, gdy są używane w ciasnych pętlach, ponieważ HotSpot nie jest prawdopodobnie zoptymalizuje obsady i instanceof
.
Jest całkiem podobny do innych operatorów porównania (np. <
/ >
) - będą wyzwalać rozpakowywanie, podczas gdy używanie compareTo()
tego nie zrobi - ale tym razem operacja jest wysoce zoptymalizowana przez HS, ponieważ intValue()
jest to tylko metoda gettera (główna kandydatka do optymalizacji).
Moim zdaniem, rzadko stosowany w wersji 4 jest najbardziej zwięzły sposób - każdy zaprawiony programista C / Java wie, że jednoargumentowy plus to w większości przypadków równa do obsady do int
/ .intValue()
- choć może to być trochę WTF moment dla niektórych (głównie tych, którzy didn nie używają jednoznacznego plusa w ciągu swojego życia), najprawdopodobniej pokazuje intencję najdokładniej i najdokładniej - pokazuje, że chcemy int
wartości jednego z argumentów, zmuszając również drugą wartość do rozpakowania. Jest również bezsprzecznie najbardziej podobny do zwykłego i1 == i2
porównania stosowanego dla pierwotnych int
wartości.
Mój głos dotyczy stylu i1 == +i2
i obiektów, zarówno ze względu na wydajność, jak i spójność. Dzięki temu kod jest przenośny dla prymitywów, nie zmieniając niczego poza deklaracją typu. Używanie nazwanych metod wydaje mi się wprowadzać do mnie hałas semantyczny, podobny do bardzo krytykowanego stylu.i1 > i2
Integer
bigInt.add(10).multiply(-3)