Два куска кода должны давать один и тот же ответ, за исключением неясного случая с краями 1 .
Существенные различия между ними:
- тест
this == obj
.
- явный
obj == null
тест.
- итоговый
if
тест
Работа с ними в обратном порядке.
Я бы не ожидал, что это будет иметь значение, написали ли вы это как obj instanceof Type
или !(obj instanceof type)
. Действительно, я ожидаю, что JIT-компилятор оптимизирует на основе «направления», которое обычно принимает ветвь, и генерирует эквивалентный код для обоих случаев.
Оператор instanceof
неявно проверяет null
, поэтому явный тест obj == null
не требуется. Тем не менее, я ожидаю, что JIT-компилятор распознает это и не сгенерирует собственный код для двойной проверки на ноль.
Тест this == obj
реализует явное «короткое замыкание» для случая, который считается часто встречающимся.
Пограничный регистр означает, что JIT-компилятор не сможет вставить эквивалентную логику короткого замыкания, если ее еще не было в исходном / байт-кодах.
Неясно, улучшится ли короткое замыкание или нет. Это зависит от фактической частоты, с которой один из этих объектов сравнивается с самим собой ... от стоимости выполнения этого.
Короче говоря, только тест this == other
может иметь значение (после JIT-компиляции), и это может или не может быть полезным для производительности.
ОДНАКО ... если производительность действительно имеет значение, сравните ее ... используя реалистичные данные для сравнения.
1 - крайний случай возникает, потому что Objects.equals(id, other.id)
может вызвать исключение или дать неправильный ответ, когда this.id
и other.id
- это один и тот же объект. Это, в свою очередь, зависит от фактической реализации Object::equals(Object)
для фактического типа времени выполнения id
.