19

Можно написать условие вот так:

if (repository == null) {}

а можно вот так:

if (null == repository) {}

В чем разница?

αλεχολυτ
  • 28,987
  • 13
  • 60
  • 119
Sirop4ik
  • 10,954
  • ни в чем. Только порядок аргументов. – Grundy Nov 23 '16 at 09:23
  • 2
    в первом случае repository сравнивается с null, во втором - null с repository – mix Nov 23 '16 at 09:24

4 Answers4

28

введите сюда описание изображения

Условиями Йоды (Yoda Conditions) называется приём этот. Первой константа ставится, если ошибётесь и используете = вместо == вы, указал на эту ошибку компилятор вам чтобы. В Java это несущественно, т.к. ошибка будет почти всегда, исключение описано в соседнем ответе.

Есть другой случай, когда порядок сравнения имеет значение в Java — .equals(). Предположим, у вас есть объект, который вы получаете извне метода и образец для сравнения.

if (foo.equals(sample)) {...}

Если сравнивать так, что может случиться, что полученный объект будет равен null и тогда будет выброшено исключение. А ещё это может быть хитрый объект, в котором .equals() переопределено так, чтобы всегда возвращать true.

Гораздо надёжнее сравнивать в обратном порядке:

if (sample.equals(foo)) {...}
Nick Volynkin
  • 34,094
  • что надежнее в сравнивании в обратном порядке, если у sample Тоже переопределен equals? – Grundy Nov 23 '16 at 09:46
  • я так понимаю что нет разницы если ни один из обьектов не является константой... – Sirop4ik Nov 23 '16 at 09:47
  • @Grundy подразумевается, что sample мы получаем надёжным способом. Например, тут же создаём новый объект известного нам класса. – Nick Volynkin Nov 23 '16 at 09:47
  • @AlekseyTimoshchenko если оба объекта "ненадёжные", то перед проверкой на equals нужно как минимум один из них проверять на != null. – Nick Volynkin Nov 23 '16 at 09:48
  • 1
    Упомянуть стоит, от null защититься чтобы, Objects.equals() использовать можно, с седьмой начиная джавы. – Roman Nov 28 '16 at 07:03
13

Некоторые наркоманы пишут наоборот, чтобы компилятор напомнил, если они напишут "=", вместо "==". Но в Java строгая типизация - null к boolean не приводится и код с ошибкой не скомпилируется в любом случае, потому разницы нет никакой. В других языках - есть.

Не Java, вместо null можно считать любую другую константу:

if (null = repository) { //compile error
...
}

if (repository = null) { // build success
...
}

В Java прокатит один частный случай:

if (condition = true) { ... }
free_ze
  • 8,656
  • а warning никакого не будет в этом случае: (repository = null)? – Grundy Nov 23 '16 at 09:29
  • 4
    Более того, в Java будет ошибка компиляции, т.к. null (как результат присваивания) не может быть преобразовано к boolean, но в большинстве Си-подобных языков такой трюк сработает. – free_ze Nov 23 '16 at 09:33
  • Вот только хотел написать про ошибку в Java :-) Там получается вообще никак не сделать второй код рабочим? – Grundy Nov 23 '16 at 09:35
  • Дополнил ответ. – free_ze Nov 23 '16 at 09:36
  • 1
    прокатит один частный случай - второй же с false – Grundy Nov 23 '16 at 09:47
  • 1
    Не Йоды условиями от "частного случая" этого защищаться надо, но недопуская кода индусского! if(condition), if (!condition) – Pavel Mayorov Dec 01 '16 at 10:58
  • @PavelMayorov кстати, да. Странно, что до сих пор никому (включая меня) не резануло глаза сравнение bool через == вместо прямого использования. – Nick Volynkin Dec 02 '16 at 16:02
  • @NickVolynkin наверное потому, что речь изначально шла о йода-стиле?) – free_ze Dec 02 '16 at 16:07
7

В принципе, в предыдущих ответах всё уже сказано, просто дополню. В Java условия Йоды с == могут быть полезны только при сравнении boolean, в двух случаях.

1. Если у вас есть метод, возвращающий boolean:

public static boolean getBool() { return true; }

и вы сравниваете результат этого метода с переменной boolean:

boolean bln = false;
if (bln == getBool()) {
    //блок if
} else {
    //блок else 
} 

В этом случае должен выполняться блок else. Но если вы вдруг ошибётесь и напишете:

if (bln = getBool()) {
    //блок if
} else {
    //блок else 
}  

компилятор не выдаст ошибки, и код выполнится, но выполняться будет блок if. Чтобы не допустить такой ошибки, лучше написать

if (getBool() == bln) {
    //блок if
} else {
    //блок else 
}

потому что написать getBool() = bln по невнимательности компилятор вам не даст.

2. Если вы сравниваете объект Boolean c null:

Boolean booleanObject = null;
if (booleanObject == null) { ... }

Если в этом случае вы вместо == случайно напишете =:

if (booleanObject = null) { ... }

код выполнится, но вы получите NullPointerException. А написать

if (null = booleanObject) { ... }

опять же, компилятор вам не даст.

P.S. Также условие Йоды в Java может быть полезно при сравнении строк с помощью equals. Например, если вы напишете

if (strVar.equals("string")) {
    //блок if
} else {
    //блок else 
}

получите ошибку в случае, если strVar было равно null, а если напишете

if ("string".equals(strVar)) {
    //блок if
} else {
    //блок else 
}

попадёте в блок else в этом же случае (если strVar было равно null).

Ksenia
  • 10,679
  • а разве NullPointerException, а не ошибку приведения? – Grundy Dec 01 '16 at 10:56
  • 2
    @Grundy, нет, NullPointerException, я проверяла :) – Ksenia Dec 01 '16 at 10:57
  • @Grundy Почему должна быть ошибка приведения? Boolean - это ссылочный тип, ему вполне можно присваивать null. А вот когда идет попытка сделать unboxing, мы и получаем NPE. – free_ze Dec 01 '16 at 11:17
  • @free_ze, не, в прошлые разы мне казалось, что как раз ошибка приведения была при сравнении :) – Grundy Dec 01 '16 at 11:18
  • @Grundy вам казалось. – free_ze Dec 01 '16 at 11:23
  • Отличные примеры! А почему equals только со строками, ведь и другие объекты могут быть Null? – Nick Volynkin Dec 02 '16 at 16:01
  • @NickVolynkin, ну да, пример с equals не только для строк справедлив, но и для других объектов (всё зависит от того, как у них этот метод equals реализован) – Ksenia Dec 02 '16 at 16:57
3

Разница в порядке сравнения =)
В Java большой разницы нет, сработает и так и эдак, только если Вы будете сравнивать null со всем подряд то програмисты которые потом будут разбирать Ваш код будут ругаться, что это за индус писал, т.к. не стоит забывать про Code Conventions.