1. Булевы операции
Операторы |
и &
можно применять не только к числам, но и к выражениям типа boolean.
Однако, как вы уже знаете, для логических выражений есть операторы &&
и ||
. Что же нам даст использование |
вместо ||
и использование &
вместо &&
? Есть ли вообще в этом смысл? Оказывается, есть. Иногда.
Логические операторы ||
и &&
выполняются слева направо по так называемому ленивому принципу.
(выражение1) || (выражение2) || (выражение3)
Если выражение1
равно true
, нет смысла вычислять выражение2
и выражение3
: результат все равно будет true
.
Поэтому при вычислении выражений (а они вычисляются по порядку слева направо), как только мы получили true
, вычисление остальных выражений пропускается. И если в выражениях выражение2
и выражение3
были вызовы каких-нибудь функций, то эти функции не вызываются!
То же самое и для логического оператора &&
:
(выражение1) && (выражение2) && (выражение3)
Если выражение1
равно false
, нет смысла вычислять выражение2
и выражение3
: результат все равно будет false
.
Это важный момент, который позволяет писать вещи вида:
String s = null;
if (s != null && s.length() > 0) {
В примере выше мы никогда не получим NullPointerException, т.к. выражение s.length()
будет выполняться только если первая часть s != null
равна true
.
Если s
окажется равно null
, слева от оператора &&
будет значение false
, и результат всего логического выражения будет false
, поэтому вычисления второй части (s.length() > 0
) не происходит.
Если в логическом выражении использовать оператор |
или оператор &
, то ленивого вычисления не происходит — в любом случае будут вычислены все выражения.
2. Приоритет операций в Java
Как вы, наверное, помните из школьного курса математики, операция умножения имеет более высокий приоритет, чем операция сложения. Скобки же имеют еще более высокий приоритет: сначала вычисляются выражения в скобках, а потом уже умножение/деление и сложение/вычитание.
Операторы в Java тоже имеют приоритет. Только: а) их несколько больше, б) у некоторых операторов действия выполняются слева направо, а у других — справа налево.
Вот как выглядит таблица со всеми операторами Java:
Категория | Оператор | Ассоциативность |
---|---|---|
Постфикс | () [] . |
Слева направо |
Унарный | ++ -- ! ~ |
Справа налево |
Мультипликативный | * / % |
Слева направо |
Аддитивный | + - |
Слева направо |
Сдвиг | >> >>> << |
Слева направо |
Реляционный | > >= < <= |
Слева направо |
Равенство | == != |
Слева направо |
Побитовое И (AND) |
& |
Слева направо |
Исключающее ИЛИ (XOR) |
^ |
Слева направо |
Побитовое ИЛИ (OR) |
| |
Слева направо |
Логическое И (AND) |
&& |
Слева направо |
Логическое ИЛИ (OR) |
|| |
Слева направо |
Условный | ?: |
Справа налево |
Присваивание | = += -= *= /= %= >>= <<= &= ^= |= |
Справа налево |
Запятая | , |
Слева направо |
В верхней строке идут самые приоритетные операторы. Круглые скобки ()
используются для явной установки приоритета. Квадратные скобки []
используются для индексирования переменной-массива. Оператор .
используется для получения полей и методов у ссылки на объект или класс.
Чем ниже операторы расположены в таблице, тем ниже их приоритет.
Если вы используете несколько операторов в вашем выражении, не ленитесь: ставьте скобки.
Да, в Java можно написать что-то типа if (a & 1<<b > ~c)
, но так делать не стоит. Вы пишете код не только для компилятора, но и для других программистов. Чем код читабельнее, тем лучше.
3. Префиксный и постфиксный инкремент
Как вы уже знаете, в Java есть оператор инкремента (++
) и оператор декремента (--
), которые увеличивают (и уменьшают) значение переменной на 1
.
Чего вы скорее всего не знаете, так это того, что есть два вида этих операций: префиксные – оператор ставится до переменной, и постфиксные — оператор ставится после переменной. И работают эти операторы немного по-разному.
В Java можно написать такое выражение:
int a = 5;
int b = a++;
Если оператор ++
стоит после переменной и переменная участвует в каком-то выражении (как в примере выше), то в выражении будет использовано текущее значение переменной, а только потом она будет увеличена на 1
.
Другими словами, произойдет примерно это:
int a = 5;
int b = a;
a = a + 1;
Т.е. b
будет иметь значение 5
, а не 6
, как это могло показаться вначале.
Если же оператор ++
стоит до переменной и переменная участвует в каком-то выражении, она сначала будет увеличена на 1
, а только затем ее значение будет участвовать в выражении.
int a = 5;
int b = ++a;
Пример выше эквивалентен следующему примеру:
int a = 5;
a = a + 1;
int b = a;
Вот тут уже значение b
будет равно 6
.
Есть даже один пример, который используется Java-программистами, чтобы определить, что их собеседник тоже Java-программист:
int a = 5;
int b = ++a + ++a;
Да, так тоже можно писать.
Этот пример отлично скомпилируется и превратится примерно в это:
int a = 5;
a = a + 1;
int v1 = a;
a = a + 1;
int v2 = a;
int b = v1 + v2;
Для оператора --
все точно то же самое.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ