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;
Для оператора -- все точно то же самое.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ