Какая разница в производительности, если таковая имеется, между if (! Foo) и if (foo == false) в Java?
Логически, if(!foo)
и if(foo == false)
эквивалентны. Как они представлены на Java? Есть ли разница между двумя после компиляции, либо в байте-коде или в производительности? Я не смог найти ответ в JLS, и поиск привел к большим результатам о действиях = vs. == typos и ==/equals(). (В этом случае символы мешали моему поиску, поскольку будущие искатели, оператор отрицания, равны ложному, равному false, а не условию).
Чтобы обсудить обсуждение CW: этот вопрос НЕ спрашивает, какой вариант предпочитают люди или который считается лучшим стилем. Меня интересуют различия в реализации языка, поэтому есть правильный ответ. Связанный-но-не-вполне-a-dupe: Разница между while (x = false) и while (! X) в Java?
EDIT:
По общему мнению, хороший компилятор должен оптимизировать их для одного и того же. Это имеет смысл и является тем, что я подозревал, но, чтобы задать еще более академический вопрос, - это то, что поведение действительно предусмотрено где угодно, или это "просто" разумная вещь?
Ответы
Ответ 1
JLS определит требуемое поведение операторов. Однако, как они реализованы, это деталь реализации компилятора и JVM.
На практике любой компилятор, заслуживающий своей соли, должен выпустить тот же байт-код для этих операторов. И даже если нет, JVM оптимизирует их правильно.
Кроме того, лучший способ ответить на этот вопрос - проверить сами, используя javap
:
-
Скомпилируйте Test.java
со следующим содержимым:
class Test {
void equals(boolean f) {
if (f == false) {}
}
void not(boolean f) {
if (!f) {}
}
}
$ javac Test.java
-
Удалите его:
$ javap -c Test
Compiled from "Test.java"
class Test extends java.lang.Object{
Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
void equals(boolean);
Code:
0: iload_1
1: ifne 4
4: return
void not(boolean);
Code:
0: iload_1
1: ifne 4
4: return
}
UPDATE:
Отвечая на вопрос о "академическом" вопросе. Как упоминалось выше, JLS касается только поведения. В стандарте нет ничего, что на самом деле указывает, как оно должно быть реализовано (ну, JVMS предоставляет много рекомендаций).
Пока компилятор сохраняет одно и то же одинаковое поведение, компилятор может реализовать его по-разному, с возможностью различной производительности выполнения.
Ответ 2
Компилятор должен решить один и тот же код внутри, поэтому нет никакой разницы.
Ответ 3
попробуйте декомпилировать байтовый код и посмотреть, как выглядит код. Я бы предположил, что компиляция разрешит их почти одинаково, и любая небольшая разница приведет к незначительной разнице в производительности.
Ответ 4
ОК, более полный ответ:
Я был бы очень удивлен, если бы какой-либо компилятор сгенерировал разные байт-коды для этих вариантов. Для всех, кто интересуется, должно быть достаточно легко проверить с помощью дизассемблера.
Учитывая, что оба выражения (скорее всего) скомпилированы в один и тот же байт-код, я не ожидаю разницы в размере или производительности.
Ответ 5
JLS говорит, что
выражение в вычисляется блок if, тогда результат этого выражения сравнивается с правда
В случаях не случайных и сравниваемых объектов выражение должно оцениваться, а затем сравниваться с истинным. Если вы проверяете значение, а не выполняете оператор на нем, может быть теоретическое преимущество в производительности, так как оценка выражения становится не op.
Но в этом случае я бы ожидал, что JIT создаст тот же байт-код для обоих выражений.
Ответ 6
Не должно быть разницы в байт-коде, сгенерированном для этих двух результатов, и если бы это было сделано, если вы не создаете код для устройства с очень ограниченными ресурсами (в этом случае вы не должны писать на Java), чем разница была бы незначительной и вы должны решить, какой из двух способов написания этого кода является более очевидным решением.
Ответ 7
Мысль о микрооптимизации почти в любом случае является пустой тратой времени и приводит к неправильному мышлению...
Ответ 8
Я задал аналогичный вопрос относительно С++/VS2008.
Будет ли компилятор VS2008 С++ оптимизировать следующий оператор if?
Чтобы избежать = vs == опечатки в С++, вы склонны писать
if (NULL == ptr) { ... }
if (false == boo) { ... }
if (20 == num) { ... }
и др.
Это немного менее читаемо, пока вы не привыкнете к нему.