tl; dr моя думка полягає у використанні одинарного+
щоб запустити розпакування на одному з операндів під час перевірки рівності значень, а просто використовувати математичні оператори в іншому випадку. Обґрунтування випливає:
Вже було зазначено, що ==
порівняння - Integer
це порівняння ідентичності, яке, як правило, не те, чого хоче програміст, а мета - порівняння цінностей; все-таки я трохи вивчив, як зробити це порівняння найефективніше, що стосується компактності коду, правильності та швидкості.
Я використовував звичайну купу методів:
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;
}
і отримав цей код після компіляції та декомпіляції:
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;
}
}
Як ви легко бачите, метод 1 викликає Integer.equals()
(очевидно), методи 2-4 призводять до точно такого ж коду , розгортаючи значення за допомогою.intValue()
а потім безпосередньо їх порівняння, а метод 5 просто запускає порівняння ідентичності, будучи неправильним способом порівняти значення.
Оскільки (як вже згадувалося, наприклад, JS) equals()
виникає накладні витрати (це має робити instanceof
і неперевірений склад), методи 2-4 будуть працювати з точно такою ж швидкістю, помітно краще, ніж метод 1 при використанні у вузьких петлях, оскільки HotSpot не є ймовірно, що оптимізуватиме ролі & instanceof
.
Це досить схоже з іншими операторами порівняння (наприклад, <
/ >
) - вони запускатимуть розблокування, а використання compareTo()
не буде, - але цього разу HS оптимізує операцію, оскільки intValue()
це лише метод getter (головний кандидат для оптимізації).
На мою думку, рідко використовувана версія 4 - це самий стислий спосіб - кожен досвідчений розробник C / Java знає, що унарний плюс у більшості випадків дорівнює int
/, .intValue()
хоча для деяких це може бути невеликим моментом WTF (переважно тим, хто цього не зробив) не використовую унарний плюс протягом свого життя), це, мабуть, показує наміри найяскравіше і найбільш коротко - це показує, що ми хочемо int
значення одного з операндів, змушуючи також розпаковувати інше значення. Крім того, воно, безумовно, найбільше схоже на регулярне i1 == i2
порівняння, яке використовується для примітивних int
значень.
Моє голосування відповідає i1 == +i2
& i1 > i2
стилю для Integer
об'єктів, як із продуктивності, так і з послідовністю. Це також робить код переносним для примітивів, не змінюючи нічого, крім декларації типу. Використання названих методів здається мені введенням смислового шуму, подібного до сильно критикованого bigInt.add(10).multiply(-3)
стилю.