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)стилю.