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()
это всего лишь метод получения (основной кандидат на оптимизацию).
На мой взгляд, редко используемая версия 4 является наиболее лаконичным способом - каждый опытный разработчик C / Java знает, что унарный плюс в большинстве случаев равен приведению к int
/, .intValue()
хотя для некоторых это может быть небольшим моментом WTF (в основном для тех, кто не использует унарный плюс в своей жизни), он, вероятно, показывает намерение наиболее четко и кратко - это показывает, что мы хотим получить int
значение одного из операндов, заставляя другое значение также распаковать. Также неоспоримо наиболее похоже на обычное i1 == i2
сравнение используется для примитивных int
значений.
Мой голос идет за i1 == +i2
и i1 > i2
стиль для Integer
объектов, как по причинам производительности, так и по соображениям согласованности. Это также делает код переносимым на примитивы, не изменяя ничего, кроме объявления типа. Использование именованных методов похоже на создание семантического шума, похожего на критикуемый bigInt.add(10).multiply(-3)
стиль.