- Операторы
- Арифметические оператор
- Четыре арифметических действия
- Пример программы, манипулирующей с битами
- Беззнаковый сдвиг вправо
- Битовые операторы присваивания
- Операторы отношения
- Булевы логические операторы
- Явные приоритеты
- Что дальше?
- Логические операторы
- Таблица логических операторов в Java
- Таблица. Результаты выполнения логических операторов
- Сокращённые логические операторы
- Тернарный оператор
Операторы
Операторы в языке Java — это специальные символы, которые сообщают транслятору о том, что вы хотите выполнить операцию с некоторыми операндами. Некоторые операторы требуют одного операнда, их называют унарными. Одни операторы ставятся перед операндами и называются префиксными, другие — после, их называют постфиксными операторами. Большинство же операторов ставят между двумя операндами, такие операторы называются инфиксными бинарными операторами. Существует тернарный оператор, работающий с тремя операндами.
В Java имеется 44 встроенных оператора. Их можно разбить на 4 класса — арифметические, битовые, операторы сравнения и логические.
Арифметические оператор
Арифметические операторы используются для вычислений так же как в алгебре (см. таблицу со сводкой арифметических операторов ниже). Допустимые операнды должны иметь числовые типы. Например, использовать эти операторы для работы с логическими типами нельзя, а для работы с типом char можно, поскольку в Java тип char — это подмножество типа int.
Оператор | Результат | Оператор | Результат |
+ | Сложение | + = | сложение с присваиванием |
— | вычитание (также унарный минус) | -= | вычитание с присваиванием |
* | Умножение | *= | умножение с присваиванием |
/ | Деление | /= | деление с присваиванием |
% | деление по модулю | %= | деление по модулю с присваиванием |
++ | Инкремент | — | декремент |
Четыре арифметических действия
Ниже, в качестве примера, приведена простая программа, демонстрирующая использование операторов. Обратите внимание на то, что операторы работают как с целыми литералами, так и с переменными.
class BasicMath < public static void int a = 1 + 1; int b = a * 3; main(String args[]) < int c = b / 4; int d = b - а; int e = -d; System.out.println("a = " + а); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); System.out.println("e x mod 10 = " + x % 10); System.out.println("y mod 10 a = " + a); System.out.println("b = " + b); System.out.println("c a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d 1" cellspacing="0" cellpadding="2">Оператор Результат Оператор Результат ~ побитовое унарное отрицание (NOT) & побитовое И (AND) &= побитовое И (AND) с присваиванием | побитовое ИЛИ (OR) |= побитовое ИЛИ (OR) с присваиванием ^ побитовое исключающее ИЛИ (XOR) ^= побитовое исключающее ИЛИ (XOR) с присваиванием >> сдвиг вправо >> = сдвиг вправо с присваиванием >>> сдвиг вправо с заполнением нулями >>>= сдвиг вправо с заполнением нулями с присваиванием сдвиг влево сдвиг влево с присваиванием Пример программы, манипулирующей с битами
В таблице, приведенной ниже, показано, как каждый из операторов битовой арифметики воздействует на возможные комбинации битов своих операндов. Приведенный после таблицы пример иллюстрирует использование этих операторов в программе на языке Java.
А В OR AND XOR NOT A 0 0 0 0 0 1 1 0 1 0 1 0 0 1 1 0 1 1 1 1 1 1 0 0 class Bitlogic < public static void main(String args []) < String binary[] = < "OOOO", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" >; int a = 3; // 0+2+1 или двоичное 0011 int b = 6; // 4+2+0 или двоичное 0110 int c = a | b; int d = a & b; int e = a ^ b; int f = (~a & b) | (a & ~b); int g = ~a & 0x0f; System.out.println(" a = " + binary[a]); System.out.println(" b = " + binary[b]); System.out.println(" ab = " + binary[c]); System.out.println(" a&b = " + binary[d]); System.out.println(" a^b = " + binary[e]); System.out.рrintln("~a&b|а^~Ь = " + binary[f]); System.out.println(" ~a b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]); > >Ниже приведен результат работы этой программы:
Беззнаковый сдвиг вправо
Часто требуется, чтобы при сдвиге вправо расширение знакового раз-ряда не происходило, а освобождающиеся левые разряды просто запол-нялись бы нулями.
class ByteUShift < static public void main(String args[]) < char hex[] = < '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'а', 'b', 'с', 'd', 'e', 'f' >; byte b = (byte) 0xf1; byte c = (byte) (b >> 4); byte d = (byte) (b >> 4); byte e = (byte) ((b & 0xff) >> 4); System.out.println(" b = 0x" + hex(b >> 4) & 0x0f] + hex[b & 0x0f]); System.out.println(" b >> 4 = 0x" + hex[(c >> 4) & 0x0f] + hex[c & 0x0f]); System.out.println("b >>> 4 = 0x" + hex[(d >> 4) & 0x0f] + hex[d & 0x0f]); System.out.println("(b & 0xff) >> 4 = 0x" + hex[(e >> 4) & 0x0f] + hex[e & 0x0f]); > >Для этого примера переменную b можно было бы инициализировать произвольным отрицательным числом, мы использовали число с шест-надцатиричным представлением 0xf1. Переменной с присваивается ре-зультат знакового сдвига b вправо на 4 разряда. Как и ожидалось, рас-ширение знакового разряда приводит к тому, что 0xf1 превращается в 0xff. Затем в переменную d заносится результат беззнакового сдвига b вправо на 4 разряда. Можно было бы ожидать, что в результате d со-держит 0x0f, однако на деле мы снова получаем 0xff. Это - результат расширения знакового разряда, выполненного при автоматическом по-вышении типа переменной b до int перед операцией сдвига вправо. На-конец, в выражении для переменной е нам удается добиться желаемого результата - значения 0x0f. Для этого нам пришлось перед сдвигом вправо логически умножить значение переменной b на маску 0xff, очис-тив таким образом старшие разряды, заполненные при автоматическом повышении типа. Обратите внимание, что при этом уже нет необходи-мости использовать беззнаковый сдвиг вправо, поскольку мы знаем со-стояние знакового бита после операции AND.
С: \> java ByteUShift b = 0xf1 b >> 4 = 0xff b >>> 4 = 0xff b & 0xff) >> 4 = 0x0fБитовые операторы присваивания
Так же, как и в случае арифметических операторов, у всех бинарных битовых операторов есть родственная форма, позволяющая автоматичес-ки присваивать результат операции левому операнду. В следующем примере создаются несколько целых переменных, с ко-торыми с помощью операторов, указанных выше, выполняются различ-ные операции.
class OpBitEquals < public static void main(String args[]) < int a = 1; int b = 2; int с = 3; a |= 4; b >>= 1; сРезультаты исполнения программы таковы:
С:\> Java OpBitEquals а = 3 b = 1 с = 6Операторы отношения
Для того, чтобы можно было сравнивать два значения, в Java имеется набор операторов, описывающих отношение и равенство. Список таких операторов приведен в таблице.
Оператор | Результат |
== | равно |
!= | не равно |
> | больше |
меньше | |
>= | больше или равно |
меньше или равно |
Значения любых типов, включая целые и вещественные числа, символы, логические значения и ссылки, можно сравнивать, используя оператор проверки на равенство == и неравенство !=. Обратите внимание - в языке Java, так же, как в С и C++ проверка на равенство обозначается последовательностью (==). Один знак (=) - это оператор присваивания.
Булевы логические операторы
Булевы логические операторы, сводка которых приведена в таблице ниже, оперируют только с операндами типа boolean. Все бинарные логические операторы воспринимают в качестве операндов два значения типа boolean и возвращают результат того же типа.
Оператор | Результат | Оператор | Результат |
& | логическое И (AND) | &= | И (AND) с присваиванием |
| | логическое ИЛИ (OR) | = | ИЛИ (OR) с присваиванием |
^ | логическое исключающее ИЛИ (XOR) | ^= | исключающее ИЛИ (XOR) с присваиванием |
|| | оператор OR быстрой оценки выражений (short circuit OR) | == | равно |
&& | оператор AND быстрой оценки выражений (short circuit AND) | != | не равно |
! | логическое унарное отрицание (NOT) | ?: | тернарный оператор if-then-else |
Результаты воздействия логических операторов на различные комбинации значений операндов показаны в таблице.
А | В | OR | AND | XOR | NOT A |
false | false | false | false | false | true |
true | false | true | false | true | false |
false | true | true | false | true | true |
true | true | true | true | false | false |
Программа, приведенная ниже, практически полностью повторяет уже знакомый вам пример BitLogic. Только но на этот раз мы работаем с булевыми логическими значениями.
class BoolLogic < public static void main(String args[]) < boolean a = true; boolean b = false; boolean с = a | b; boolean d = a & b; boolean e = a ^ b; boolean f = (!a & b) | (a & !b); boolean g = !a; System.out.println(" a = " + a); System.out.println(" b = " + b); System.out.println(" a|b = " + c); System.out.println(" a&b = " + d); System.out.println(" a^b = " + e); System.out.println("!a&b|a&!b = " + f); System.out.println(" !a a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); System.out.println("a / b = " + e); System.out.println("c / d 1" cellspacing="0" cellpadding="2" width="60%">Высший ( ) [ ] . ~ ! * / % + - >> >>> > >= == != & ^ | && | | ?: = op= Низший В первой строке таблицы приведены три необычных оператора, о которых мы пока не говорили. Круглые скобки () используются для явной установки приоритета. Как вы узнали из предыдущей главы, квадратные скобки [] используются для индексирования переменной-массива. Оператор . (точка) используется для выделения элементов из ссылки на объект - об этом мы поговорим в главе 7. Все же остальные операторы уже обсуждались в этой главе.
Явные приоритеты
Поскольку высший приоритет имеют круглые скобки, вы всегда можете добавить в выражение несколько пар скобок, если у вас есть сомнения по поводу порядка вычислений или вам просто хочется сделать свои код более читабельным.
а >> b + 3Какому из двух выражений, а >> (b + 3) или (а >> b) + 3, соответствует первая строка? Поскольку у оператора сложения более высокий приоритет, чем у оператора сдвига, правильный ответ - а>> (b + а). Так что если вам требуется выполнить операцию (а>>b)+ 3 без скобок не обойтись.
Что дальше?
Итак, мы рассмотрели все виды операторов языка Java. Теперь вы можете сконструировать любое выражение с различными типами данных. В следующей главе познакомимся с конструкциями ветвления, организацией циклов и научимся управлять выполнением программы.
Логические операторы
Логические операторы работают только с операндами типа boolean. Все логические операторы с двумя операндами объединяют два логических значения, образуя результирующее логическое значения. Не путайте с побитовыми логическими операторами.
Таблица логических операторов в Java
Оператор | Описание |
---|---|
& | Логическое AND (И) |
&& | Сокращённое AND |
| | Логическое OR (ИЛИ) |
|| | Сокращённое OR |
^ | Логическое XOR (исключающее OR (ИЛИ)) |
! | Логическое унарное NOT (НЕ) |
&= | AND с присваиванием |
|= | OR с присваиванием |
^= | XOR с присваиванием |
== | Равно |
!= | Не равно |
?: | Тернарный (троичный) условный оператор |
Логические операторы &, |, ^ действуют применительно к значениям типа boolean точно так же, как и по отношению к битам целочисленных значений. Логический оператор ! инвертирует (меняет на противоположный) булево состояние: !true == false и !false == true.
Таблица. Результаты выполнения логических операторов
A | B | A | B | A & B | A ^ B | !A |
---|---|---|---|---|---|
false | false | false | false | false | true |
true | false | true | false | true | false |
false | true | true | false | true | true |
true | true | true | true | false | false |
Сокращённые логические операторы
Кроме стандартных операторов AND (&) и OR (|) существуют сокращённые операторы && и ||.
Если взглянуть на таблицу, то видно, что результат выполнения оператора OR равен true, когда значение операнда A равно true, независимо от значения операнда B. Аналогично, результат выполнения оператора AND равен false, когда значение операнда A равно false, независимо от значения операнда B. Получается, что нам не нужно вычислять значение второго операнда, если результат можно определить уже по первому операнду. Это становится удобным в тех случаях, когда значение правого операнда зависит от значения левого.
Рассмотрим следующий пример. Допустим, мы ввели правило - кормить или не кормить кота в зависимости от числа пойманных мышек в неделю. Причём число мышек зависит от веса кота. Чем больше кот, тем больше он должен поймать мышей.
Кот, прочитавший условие задачи, обиделся на меня. Он заявил, что я отстал от жизни, а на дворе 21 век - мышей можно ловить с помощью мышеловок. Пришлось объяснять ему, что это всего лишь задачка, а не пример из личной жизни.
int mouse; // число мышек int weight; // вес кота в граммах mouse = 5; weight = 4500; if (mouse != 0 & weight / mouse
Если запустить программу, то пример будет работать без проблем - пять мышей в неделю вполне достаточно, чтобы побаловать кота вкусным завтраком. Если он поймает четырёх мышей, то начнутся проблемы с питанием кота, но не с программой - она будет работать, просто не будет выводить сообщение о разрешении покормить дармоеда.
Теперь возьмём крайний случай. Кот обленился и не поймал ни одной мышки. Значение переменной mouse будет равно 0, а в выражении есть оператор деления. А делить на 0 нельзя и наша программа закроется с ошибкой. Казалось бы, мы предусмотрели вариант с 0, но Java вычисляет оба выражения mouse != 0 и weight / mouse < 1000, несмотря на то, что уже в первом выражении возвращается false.
Перепишем условие следующим образом (добавим всего лишь один символ):
if (mouse != 0 && weight / mouse
Теперь программа работает без краха. Как только Java увидела, что первое выражение возвращает false, то второе выражение с делением просто игнорируется.
Сокращённые варианты операторов AND и OR принято использовать в тех ситуациях, когда требуются операторы булевой логики, а их односимвольные родственники используются для побитовых операций.
Тернарный оператор
В языке Java есть также специальный тернарный условный оператор, которым можно заменить определённые типы операторов if-then-else - это оператор ?:
Тернарный оператор использует три операнда. Выражение записывается в следующей форме:
логическоеУсловие ? выражение1 : выражение2
Если логическоеУсловие равно true, то вычисляется выражение1 и его результат становится результатом выполнения всего оператора. Если же логическоеУсловие равно false, то вычисляется выражение2, и его значение становится результатом работы оператора. Оба операнда выражение1 и выражение2 должны возвращать значение одинакового (или совместимого) типа.
Рассмотрим пример, в котором переменной absval присваивается абсолютное значение переменной val.
int absval, val; val = 5; absval = val < 0 ? -val : val; // выводим число mInfoTextView.setText("" + absval); val = -5; absval = val < 0 ? -val : val; mInfoTextView.setText("" + absval);
Переменной absval будет присвоено значение переменной val, если значение больше или равно нулю (вторая часть выражения). Если значение переменной val отрицательное, то переменной absval присваивается значение переменной, взятое со знаком минус, в результате минус на минус даст плюс, то есть положительно значение. Перепишем код с использованием if-else:
Другой пример с тернарным оператором можете посмотреть здесь.