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)
.