Сложение и вычитание массивов java. Операция приведения типов. Арифметические бинарные операции
Последнее обновление: 30.10.2018
Большинство операций в Java аналогичны тем, которые применяются в других си-подобных языках. Есть унарные операции (выполняются над одним операндом), бинарные - над двумя операндами, а также тернарные - выполняются над тремя операндами. Операндом является переменная или значение (например, число), участвующее в операции. Рассмотрим все виды операций.
В арифметических операциях участвуют числами. В Java есть бинарные арифметические операции (производятся над двумя операндами) и унарные (выполняются над одним операндом). К бинарным операциям относят следующие:
операция сложения двух чисел:
Int a = 10; int b = 7; int c = a + b; // 17 int d = 4 + b; // 11
операция вычитания двух чисел:
Int a = 10; int b = 7; int c = a - b; // 3 int d = 4 - a; // -6
операция умножения двух чисел
Int a = 10; int b = 7; int c = a * b; // 70 int d = b * 5; // 35
операция деления двух чисел:
Int a = 20; int b = 5; int c = a / b; // 4 double d = 22.5 / 4.5; // 5.0
При делении стоит учитывать, так как если в операции участвуют два целых числа, то результат деления будет округляться до целого числа, даже если результат присваивается переменной float или double:
Double k = 10 / 4; // 2 System.out.println(k);
Чтобы результат представлял числос плавающей точкой, один из операндов также должен представлять число с плавающей точкой:
Double k = 10.0 / 4; // 2.5 System.out.println(k);
получение остатка от деления двух чисел:
Int a = 33; int b = 5; int c = a % b; // 3 int d = 22 % 4; // 2 (22 - 4*5 = 2)
Также есть две унарные арифметические операции, которые производятся над одним числом: ++ (инкремент) и -- (декремент). Каждая из операций имеет две разновидности: префиксная и постфиксная:
++ (префиксный инкремент)
Предполагает увеличение переменной на единицу, например, z=++y (вначале значение переменной y увеличивается на 1, а затем ее значение присваивается переменной z)
Int a = 8; int b = ++a; System.out.println(a); // 9 System.out.println(b); // 9
++ (постфиксный инкремент)
Также представляет увеличение переменной на единицу, например, z=y++ (вначале значение переменной y присваивается переменной z, а потом значение переменной y увеличивается на 1)
Int a = 8; int b = a++; System.out.println(a); // 9 System.out.println(b); // 8
-- (префиксный декремент)
уменьшение переменной на единицу, например, z=--y (вначале значение переменной y уменьшается на 1, а потом ее значение присваивается переменной z)
Int a = 8; int b = --a; System.out.println(a); // 7 System.out.println(b); // 7
-- (постфиксный декремент)
z=y-- (сначала значение переменной y присваивается переменной z, а затем значение переменной y уменьшается на 1)
Int a = 8; int b = a--; System.out.println(a); // 7 System.out.println(b); // 8
Приоритет арифметических операций
Одни операции имеют больший приоритет чем другие и поэтому выполняются вначале. Операции в порядке уменьшения приоритета:
++ (инкремент), -- (декремент)
* (умножение), / (деление), % (остаток от деления)
+ (сложение), - (вычитание)
Приоритет операций следует учитывать при выполнении набора арифметических выражений:
Int a = 8; int b = 7; int c = a + 5 * ++b; System.out.println(c); // 48
Вначале будет выполняться операция инкремента ++b , которая имеет больший приоритет - она увеличит значение переменной b и возвратит его в качестве результата. Затем выполняется умножение 5 * ++b , и только в последнюю очередь выполняется сложение a + 5 * ++b
Скобки позволяют переопределить порядок вычислений:
Int a = 8; int b = 7; int c = (a + 5) * ++b; System.out.println(c); // 104
Несмотря на то, что операция сложения имеет меньший приоритет, но вначале будет выполняться именно сложение, а не умножение, так как операция сложения заключена в скобки.
Ассоциативность операций
Кроме приоритета операции отличаются таким понятием как ассоциативность . Когда операции имеют один и тот же приоритет, порядок вычисления определяется ассоциативностью операторов. В зависимости от ассоциативности есть два типа операторов:
Левоассоциативные операторы, которые выполняются слева направо
Правоассоциативные операторы, которые выполняются справа налево
Так, некоторые операции, например, операции умножения и деления, имеют один и тот же приоритет. Какой же тогда будет результат в выражении:
Int x = 10 / 5 * 2;
Стоит нам трактовать это выражение как (10 / 5) * 2 или как 10 / (5 * 2) ? Ведь в зависимости от трактовки мы получим разные результаты.
Поскольку все арифметические операторы (кроме префиксного инкремента и декремента) являются левоассоциативными, то есть выполняются слева направо. Поэтому выражение 10 / 5 * 2 необходимо трактовать как (10 / 5) * 2 , то есть результатом будет 4.
Операции с числами с плавающей точкой
Следует отметить, что числа с плавающей точкой не подходят для финансовых и других вычислений, где ошибки при округлении могут быть критичными. Например:
Double d = 2.0 - 1.1; System.out.println(d);
В данном случае переменная d будет равна не 0.9, как можно было бы изначально предположить, а 0.8999999999999999. Подобные ошибки точности возникают из-за того, что на низком уровне для представления чисел с плавающей точкой применяется двоичная система, однако для числа 0.1 не существует двоичного представления, также как и для других дробных значений. Поэтому если в таких случаях обычно применяется класс BigDecimal, который позволяет обойти подобные сиуации.
Java предоставляет богатый набор операторов для управления переменными. Все операторы Java можно разделить на следующие группы:
- арифметические операторы;
- операторы сравнения;
- побитовые операторы;
- логические операторы;
- операторы присваивания;
- прочие операторы.
Арифметические операторы
Арифметические операторы - используются в математических выражениях таким же образом, как они используются в алгебре. Предположим, целая переменная A равна 10, а переменная B равна 20. В следующей таблице перечислены арифметические операторы в Java:
Пример
Следующий простой пример показывает программно арифметические операторы. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:
Public class Test { public static void main(String args) { int a = 10; int b = 20; int c = 25; int d = 25; System.out.println("a + b = " + (a + b)); System.out.println("a - b = " + (a - b)); System.out.println("a * b = " + (a * b)); System.out.println("b / a = " + (b / a)); System.out.println("b % a = " + (b % a)); System.out.println("c % a = " + (c % a)); System.out.println("a++ = " + (a++)); System.out.println("b-- = " + (a--)); // Проверьте разницу в d++ и ++d System.out.println("d++ = " + (d++)); System.out.println("++d = " + (++d)); } }
A + b = 30 a - b = -10 a * b = 200 b / a = 2 b % a = 0 c % a = 5 a++ = 10 b-- = 11 d++ = 25 ++d = 27
Операторы сравнения
Есть следующие операторы сравнения, поддерживаемые на языке Java. Предположим, переменная A равна 10, а переменная B равна 20. В следующей таблице перечислены реляционные операторы или операторы сравнения в Java:
Оператор | Описание | Пример |
== | Проверяет, равны или нет значения двух операндов, если да, то условие становится истинным | (A == B) - не верны |
!= | Проверяет, равны или нет значения двух операндов, если значения не равны, то условие становится истинным | (A != B) - значение истинна |
> | Проверяет, является ли значение левого операнда больше, чем значение правого операнда, если да, то условие становится истинным | (A > B) - не верны |
Проверяет, является ли значение левого операнда меньше, чем значение правого операнда, если да, то условие становится истинным | (A | |
>= | Проверяет, является ли значение левого операнда больше или равно значению правого операнда, если да, то условие становится истинным | (A >= B) - значение не верны |
Проверяет, если значение левого операнда меньше или равно значению правого операнда, если да, то условие становится истинным | (A |
Пример
Следующий простой пример показывает, программно операторы сравнения в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:
Public class Test { public static void main(String args) { int a = 10; int b = 20; System.out.println("a == b = " + (a == b)); System.out.println("a != b = " + (a != b)); System.out.println("a > b = " + (a > b)); System.out.println("a = a = " + (b >= a)); System.out.println("b
A == b = false a != b = true a > b = false a = a = true b
Побитовые операторы
Java определяет несколько побитовых операторов, которые могут быть применены для целочисленных типов: int, long, short, char и byte. В Java побитовый оператор работает над битами и выполняет операцию бит за битом. Предположим, если a = 60; и b = 13; то в двоичном формате они будут следующие:
a = 0011 1100
b = 0000 1101
-----------------
a&b = 0000 1100
a|b = 0011 1101
a^b = 0011 0001
~a = 1100 0011
Предположим целочисленные переменная A равна 60, а переменная B равна 13. В следующей таблице перечислены побитовые операторы в Java:
Оператор | Описание | Пример |
& (побитовое и) | Бинарный оператор AND копирует бит в результат, если он существует в обоих операндах. | (A & B) даст 12, который является 0000 1100 |
| (побитовое или) | Бинарный оператор OR копирует бит, если он существует в любом из операндов. | (A | B) даст 61 который равен 0011 1101 |
^ (побитовое логическое или) | Бинарный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. | (A ^ B) даст 49, которая является 0011 0001 |
~ (побитовое дополнение) | Бинарный оператор дополнения и имеет эффект «отражения» бит. | (~ A) даст -61, которая является формой дополнением 1100 0011 в двоичной записи |
Бинарный оператор сдвига влево. Значение левых операндов перемещается влево на количество бит, заданных правым операндом. | A | |
>> (сдвиг вправо) | Бинарный оператор сдвига вправо. Значение правых операндов перемещается вправо на количество бит, заданных левых операндом. | A >> 2 даст 15, который является 1111 |
>>> (нулевой сдвиг вправо) | Нулевой оператор сдвига вправо. Значение левых операндов перемещается вправо на количество бит, заданных правым операндом, а сдвинутые значения заполняются нулями. | A >>> 2 даст 15, который является 0000 1111 |
Пример
Следующий простой пример показывает, программно побитовые операторы в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:
Public class Test { public static void main(String args) { int a = 60; /* 60 = 0011 1100 */ int b = 13; /* 13 = 0000 1101 */ int c = 0; c = a & b; /* 12 = 0000 1100 */ System.out.println("a & b = " + c); c = a | b; /* 61 = 0011 1101 */ System.out.println("a | b = " + c); c = a ^ b; /* 49 = 0011 0001 */ System.out.println("a ^ b = " + c); c = ~a; /*-61 = 1100 0011 */ System.out.println("~a = " + c); c = a > 2; /* 215 = 1111 */ System.out.println("a >> 2 = " + c); c = a >>> 2; /* 215 = 0000 1111 */ System.out.println("a >>> 2 = " + c); } }
Будет получен следующий результат:
A & b = 12 a | b = 61 a ^ b = 49 ~a = -61 a > 15 a >>> 15
Логические операторы
Предположим, логическая переменная A имеет значение true, а переменная B хранит false. В следующей таблице перечислены логические операторы в Java:
Пример
Public class Test { public static void main(String args) { boolean a = true; boolean b = false; System.out.println("a && b = " + (a&&b)); System.out.println("a || b = " + (a||b)); System.out.println("!(a && b) = " + !(a && b)); } }
Это произведет следующий результат:
A && b = false a || b = true !(a && b) = true
Операторы присваивания
Существуют следующие операторы присваивания, поддерживаемые языком Java:
Оператор | Описание | Пример |
= | Простой оператор присваивания, присваивает значения из правой стороны операндов к левому операнду | C = A + B, присвоит значение A + B в C |
+= | Оператор присваивания «Добавления», он присваивает левому операнду значения правого | C += A, эквивалентно C = C + A |
-= | Оператор присваивания «Вычитания», он вычитает из правого операнда левый операнд | C -= A, эквивалентно C = C - A |
*= | Оператор присваивания «Умножение», он умножает правый операнд на левый операнд | C * = A эквивалентно C = C * A |
/= | Оператор присваивания «Деление», он делит левый операнд на правый операнд | C /= A эквивалентно C = C / A |
%= | Оператор присваивания «Модуль», он принимает модуль, с помощью двух операндов и присваивает его результат левому операнду | C %= A, эквивалентно C = C % A |
Оператор присваивания «Сдвиг влево» | C | |
>>= | Оператор присваивания «Сдвиг вправо» | C >>= 2, это как C = C >> 2 |
&= | Оператор присваивания побитового «И» («AND») | C &= 2, это как C = C & 2 |
^= | Оператор присваивания побитового исключающего «ИЛИ» («XOR») | C ^= 2, это как C = C ^ 2 |
|= | Оператор присваивания побитового «ИЛИ» («OR») | C |= 2, это как C = C | 2 |
Пример
Следующий простой пример показывает, программно логические операторы в Java. Скопируйте и вставьте следующий java-код в файл test.java, скомпилируйте и запустить эту программу:
Public class Test { public static void main(String args) { int a = 10; int b = 20; int c = 0; c = a + b; System.out.println("c = a + b = " + c); c += a ; System.out.println("c += a = " + c); c -= a ; System.out.println("c -= a = " + c); c *= a ; System.out.println("c *= a = " + c); a = 10; c = 15; c /= a ; System.out.println("c /= a = " + c); a = 10; c = 15; c %= a ; System.out.println("c %= a = " + c); c >= 2 ; System.out.println("c >>= 2 = " + c); c >>= 2 ; System.out.println("c >>= a = " + c); c &= a ; System.out.println("c &= 2 = " + c); c ^= a ; System.out.println("c ^= a = " + c); c |= a ; System.out.println("c |= a = " + c); } }
Будет получен следующий результат:
C = a + b = 30 c += a = 40 c -= a = 30 c *= a = 300 c /= a = 1 c %= a = 5 c >= 2 = 5 c >>= 2 = 1 c &= a = 0 c ^= a = 10 c |= a = 10
Прочие операторы
Есть несколько других операторов, поддерживаемых языком Java.
Тернарный оператор или условный оператор (?:)
Тернарный оператор - оператор, который состоит из трех операндов и используется для оценки выражений типа boolean. Тернарный оператор в Java также известен как условный оператор. Этот. Цель тернарного оператора или условного оператора заключается в том, чтобы решить, какое значение должно быть присвоено переменной. Оператор записывается в виде:
Переменная x = (выражение) ? значение if true: значение if false
Пример
Ниже приведен пример:
Public class Test { public static void main(String args){ int a , b; a = 10; b = (a == 1) ? 20: 30; System.out.println("Значение b: " + b); b = (a == 10) ? 20: 30; System.out.println("Значение b: " + b); } }
Будет получен следующий результат:
Значение b: 30 Значение b: 20
Оператор instanceof
Оператор instanceof - проверяет, является ли объект определенного типа (типа класса или типа интерфейса) и используется только для переменных ссылочного объекта. Оператор instanceof записывается в виде:
(Переменная ссылочного объекта) instanceof (класс/тип интерфейса)
Примеры
Если переменная ссылочного объекта в левой части оператора проходит проверку для класса/типа интерфейса на правой стороне, результатом будет значение true. Ниже приведен пример и описание оператора instanceof:
Public class Test { public static void main(String args){ String name = "Олег"; // Следующее вернётся верно, поскольку тип String boolean result = name instanceof String; System.out.println(result); } }
Будет получен следующий результат:
Этот оператор по-прежнему будет возвращать значение true, если сравниваемый объект является совместимым с типом на право назначения. Ниже приводится еще один пример:
Class Vehicle {} public class Car extends Vehicle { public static void main(String args){ Vehicle a = new Car(); boolean result = a instanceof Car; System.out.println(result); } }
Будет получен следующий результат:
Приоритет операторов в Java
Приоритет операторов определяет группирование терминов в выражении. Это влияет как вычисляется выражение. Некоторые операторы имеют более высокий приоритет, чем другие; например оператор умножения имеет более высокий приоритет, чем оператор сложения:
Например, x = 7 + 3 * 2. Здесь x присваивается значение 13, не 20, потому что оператор «*» имеет более высокий приоритет, чем «+», так что сначала перемножается «3 * 2», а затем добавляется «7».
В таблице операторы с наивысшим приоритетом размещаются в верхней части, и уровень приоритета снижается к нижней части таблицы. В выражении высокий приоритет операторов в Java будет оцениваться слева направо.
Категория | Оператор | Ассоциативность |
Постфикс | () . (точка) | Слева направо |
Унарный | ++ - - ! ~ | Справа налево |
Мультипликативный | * / % | Слева направо |
Аддитивный | + - | Слева направо |
Сдвиг | >> >>> | Слева направо |
Реляционный | > >= | Слева направо |
Равенство | == != | Слева направо |
Побитовое «И» («AND») | & | Слева направо |
Побитовое исключающее «ИЛИ» («XOR») | ^ | Слева направо |
Побитовое «ИЛИ» («OR») | | | Слева направо |
Логическое «И» («AND») | && | Слева направо |
Логическое «ИЛИ» («OR») | || | Слева направо |
Условный | ?: | Справа налево |
Присваивание | = += -= *= /= %= >>= | Справа налево |
Запятая | , | Слева направо |
В следующем уроке поговорим об управлении циклом в программировании на Java. В этом уроке будут описаны различные типы циклов, как циклы могут быть использованы в разработке программ, и для каких целей они используются.
Логические операторы работают только с операндами типа boolean . Все логические операторы с двумя операндами объединяют два логических значения, образуя результирующее логическое значения. Не путайте с .
Таблица логических операторов в Java
Логические операторы & , | , ^ действуют применительно к значениям типа 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 true , независимо от значения операнда B. Аналогично, результат выполнения оператора AND равен false , когда значение операнда A равно false , независимо от значения операнда B. Получается, что нам не нужно вычислять значение второго операнда, если результат можно определить уже по первому операнду. Это становится удобным в тех случаях, когда значение правого операнда зависит от значения левого.
Рассмотрим следующий пример. Допустим, мы ввели правило - кормить или не кормить кота в зависимости от числа пойманных мышек в неделю. Причём число мышек зависит от веса кота. Чем больше кот, тем больше он должен поймать мышей.
Кот, прочитавший условие задачи, обиделся на меня. Он заявил, что я отстал от жизни, а на дворе 21 век - мышей можно ловить с помощью мышеловок. Пришлось объяснять ему, что это всего лишь задачка, а не пример из личной жизни.
Int mouse; // число мышек int weight; // вес кота в граммах mouse = 5; weight = 4500; if (mouse != 0 & weight / mouse < 1000) { mInfoTextView.setText("Можно кормить кота"); }
Если запустить программу, то пример будет работать без проблем - пять мышей в неделю вполне достаточно, чтобы побаловать кота вкусным завтраком. Если он поймает четырёх мышей, то начнутся проблемы с питанием кота, но не с программой - она будет работать, просто не будет выводить сообщение о разрешении покормить дармоеда.
Теперь возьмём крайний случай. Кот обленился и не поймал ни одной мышки. Значение переменной mouse будет равно 0, а в выражении есть оператор деления. А делить на 0 нельзя и наша программа закроется с ошибкой. Казалось бы, мы предусмотрели вариант с 0, но Java вычисляет оба выражения mouse != 0 и weight / mouse < 1000 , несмотря на то, что уже в первом выражении возвращается false .
Перепишем условие следующим образом (добавим всего лишь один символ):
If (mouse != 0 && weight / mouse < 1000) { mInfoTextView.setText("Можно кормить кота"); }
Теперь программа работает без краха. Как только 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 :
If(val < 0) absval = -val; else absval = val;
Другой пример с тернарным оператором можете посмотреть .
Мне кажется, давно уже пора приступить к разработке документа, в котором будет четко оговорено, что граждане могут делать в свое свободное время, а чего они делать не должны.
Из к/ф «Забытая мелодия для флейты»
Все операторы Java можно разделить на четыре группы: арифметические, логиче- ские, побитовые и сравнения. Рассмотрим последовательно каждую группу опе- раторов. Начнем с арифметических. Эти операторы перечислены в табл. 1.2.
Таблица 1.2. Арифметические операторы Java
Оператор | Название | Пояснение |
+ | Сложение | Бинарный оператор. Результатом команды a+b являет- ся сумма значений переменных a и b |
- | Вычитание | Бинарный оператор. Результатом команды a-b являет- ся разность значений переменных a и b |
* | Умножение | Бинарный оператор. Результатом команды a*b являет- ся произведение значений переменных a и b |
/ | Деление | Бинарный оператор. Результатом команды a/b являет- ся частное от деления значений переменных a и b. Для целочисленных операндов по умолчанию выполняется деление нацело |
% | Остаток | Бинарный оператор. Результатом команды a%b яв- ляется остаток от целочисленного деления значений переменных a и b |
+= | Сложение (упро- щенная форма с присваиванием) | Упрощенная форма оператора сложения с присваива- нием. Команда a+=b является эквивалентом команды a=a+b |
-= | Вычитание (упро- щенная форма с присваиванием) | Упрощенная форма оператора вычитания с присваива- нием. Команда a-=b является эквивалентом команды a=a-b |
*= | Умножение (упро- щенная форма с присваиванием) | Упрощенная форма оператора умножения с присваи- ванием. Команда a*=b является эквивалентом команды a=a*b |
/= | Деление (упро- щенная форма с присваиванием) | Упрощенная форма оператора деления с присваива- нием. Команда a/=b является эквивалентом команды a=a/b |
%= | Остаток (упро- щенная форма) | Упрощенная форма оператора вычисления остатка с присваиванием. Команда a%=b является эквивален- том команды a=a%b |
++ | Инкремент | Унарный оператор. Команда a++ (или ++a) является эквивалентом команды a=a+1 |
-- | Декремент | Унарный оператор. Команда a-- (или --a) является эквивалентом команды a=a-1 |
Эти операторы имеют некоторые особенности. В первую очередь обращаем вни- мание на оператор деления /. Если операндами являются целые числа, в ка- честве значения возвращается результат целочисленного деления. Рассмотрим последовательность команд:
int a=5,b=2; double x=a/b;
В данном примере переменная x получает значение 2.0, а не 2.5, как можно было бы ожидать. Дело в том, что сначала вычисляется выражение a/b. Поскольку
операнды целочисленные, выполняется целочисленное деление. И только по- сле этого полученное значение преобразуется к формату double и присваивается переменной x.
Для того чтобы при целочисленных операндах выполнялось обычное деление, перед выражением с оператором деления указывается в круглых скобках иден- тификатор типа double (или float). Например, так:
double x=(double)a/b;
Теперь значение переменной x равно 2.5.
В Java, как и в С++, есть группа упрощенных арифметических операторов с присваиванием. Если op - один из операторов сложения, умножения, деления и вычисления остатка, то упрощенная форма этого оператора с присваиванием имеет вид op=. Это тоже бинарный оператор, как и оператор op, а команда вида x op=y является эквивалентом команды x=x op y.
Еще два исключительно полезных унарных оператора - операторы инкремента (++) и декремента (--). Действие оператора декремента сводится к увеличению на единицу значения операнда, а оператор декремента на единицу уменьшает операнд. Другими словами, команда x++ эквивалентна команде x=x+1, а команда x-- эквивалентна команде x=x-1. У операторов инкремента и декремента есть не только представленная здесь постфиксная форма (оператор следует после опе- ранда: x++ или x--), но и префиксная (оператор располагается перед операндом:
X или --x). С точки зрения действия на операнд нет разницы в том, префикс- ная или постфиксная формы оператора использованы. Однако если выражение с оператором инкремента или декремента является частью более сложного вы- ражения, различие в префиксной и постфиксной формах операторов инкремента и декремента существует. Если использована префиксная форма оператора, сна- чала изменяется значение операнда, а уже после этого вычисляется выражение. Если использована постфиксная форма оператора, сначала вычисляется выраже- ние, а затем изменяется значение операнда. Рассмотрим небольшой пример:
В этом случае после выполнения команд переменная n будет иметь значение 11, а переменная m - значение 10. На момент выполнения команды m=n++ значение переменной n равно 10. Поскольку в команде m=n++ использована постфиксная форма оператора инкремента, то сначала выполняется присваивание значения переменной m, а после этого значение переменной n увеличивается на единицу.
Иной результат выполнения следующих команд:
Обе переменные (n и m) в этом случае имеют значение 11. Поскольку в команде m=++n использована префиксная форма инкремента, сначала на единицу увели- чивается значение переменной n, а после этого значение переменной n присваи- вается переменной m.
Следующую группу образуют логические операторы. Операндами логических операторов являются переменные и литералы типа boolean. Логические опера- торы Java перечислены в табл. 1.3.
Таблица 1.3. Логические операторы Java
Оператор | Название | Пояснение |
& | Логическое И | Бинарный оператор. Результатом операции A&B явля- ется true, если значения обоих операндов равны true. В противном случае возвращается значение false |
&& | Сокращенное логическое И | Бинарный оператор. Особенность оператора, по срав- нению с оператором &, состоит в том, что если значе- ние первого операнда равно false, то значение второго операнда не проверяется |
| | Логическое ИЛИ | Бинарный оператор. Результатом операции A|B являет- ся true, если значение хотя бы одного операнда равно true. В противном случае возвращается значение false |
|| | Сокращенное логическое ИЛИ | Бинарный оператор. Особенность оператора, по срав- нению с оператором |, состоит в том, что если значе- ние первого операнда равно true, то значение второго операнда не проверяется |
^ | Исключающее ИЛИ | Бинарный оператор. Результатом операции A^B являет- ся true, если значение одного и только одного опе- ранда равно true. В противном случае возвращается значение false |
! | Логическое отрицание | Унарный оператор. Результатом команды!A является true, если значение операнда A равно false. Если зна- чение операнда A равно true, результатом команды!A является значение false |
Логические операторы обычно используются в качестве условий в условных операторах и операторах цикла.
В табл. 1.4 перечислены операторы сравнения, используемые в Java.
Таблица 1.4. Операторы сравнения Java
Оператор | Название | Пояснение |
< | Меньше | Результатом операции A |
<= | Меньше или равно | Результатом операции A<=B является значения true, если значение операнда A не больше значения операн- да B. В противном случае значением является false |
> | Больше | Результатом операции A>B является значения true, если значение операнда A больше значения операнда B. В противном случае значением является false |
>= | Больше или равно | Результатом операции A>=B является значения true, если значение операнда A не меньше значения опе- ранда B. В противном случае значением является false |
!= | Не равно | Результатом операции A!=B является значения true, если операнды A и B имеют разные значения. В про- тивном случае значением является false |
Операторы сравнения обычно используются совместно с логическими операто- рами.
Для понимания принципов работы поразрядных операторов необходимо иметь хотя бы элементарные познания о двоичном представлении чисел. Напомним читателю некоторые основные моменты.
В двоичном представлении позиционная запись числа содержит нули и еди- ницы.
Старший бит (самый первый слева) определяет знак числа. Для положитель- ных чисел старший бит равен нулю, для отрицательных - единице.
Перевод из двоичной системы счисления положительного числа с позицион-
ной записью
bnbn -1...b 2b 1b 0
(bi могут принимать значения 0 или 1, старший
бит для положительных чисел bn = 0) в десятичную выполняется так:
n -1 n
+ ... + bn -12
Для перевода отрицательного двоичного числа в десятичное представление производится побитовое инвертирование кода (об операции побитового ин- вертирования - см. далее), полученное двоичное число переводится в деся- тичную систему, к нему прибавляется единица (и добавляется знак минус).
Для перевода отрицательного числа из десятичной в двоичную систему от модуля числа отнимают единицу, результат переводят в бинарный код и затем этот код инвертируют.
Умножение числа на два эквивалентно сдвигу влево на один бит позиционной записи числа (с заполнением первого бита нулем).
Побитовые операторы Java описаны в табл. 1.5.
Таблица 1.5. Побитовые операторы Java
Оператор | Название | Пояснение |
& | Побитовое И | Бинарный оператор. Логическая операция И приме- няется к каждой паре битов операндов. Результатом является 1, если каждый из двух сравниваемых битов равен 1. В противном случае результат равен 0 |
| | Побитовое ИЛИ | Бинарный оператор. Логическая операция ИЛИ при- меняется к каждой паре битов операндов. Результатом является 1, если хотя бы один из двух сравниваемых битов равен 1. В противном случае результат равен 0 |
^ | Побитовое ИСКЛЮЧА- ЮЩЕЕ ИЛИ | Бинарный оператор. Логическая операция ИСКЛЮЧАЮЩЕЕ ИЛИ применяется к каждой паре битов операндов. Результатом является 1, если один и только один из двух сравниваемых битов равен 1. В противном случае результат равен 0 |
~ | Побитовое отрицание | Унарный оператор. Выполняется инверсия двоичного кода: 0 меняется на 1, а 1 меняется на 0 |
>> | Сдвиг вправо | Бинарный оператор. Результатом является число, получаемое сдвигом вправо в позиционном пред- ставлении первого операнда (слева от оператора) на количество битов, определяемых вторым операндом (справа от оператора). Исходное значение перво- го операнда при этом не меняется. Младшие биты теряются, а старшие заполняются дублированием знакового бита |
<< | Сдвиг влево | Бинарный оператор. Результатом является число, получаемое сдвигом влево в позиционном представле- нии первого операнда (слева от оператора) на количе- ство битов, определяемых вторым операндом (справа от оператора). Исходное значение первого операнда при этом не меняется. Младшие биты заполняются нулями, а старшие теряются |
>>> | Беззнаковый сдвиг вправо | Бинарный оператор. Результатом является число, по- лучаемое сдвигом вправо в позиционном представле- нии первого операнда (слева от оператора) на количе- ство битов, определяемых вторым операндом (справа от оператора). Исходное значение первого операнда при этом не меняется. Младшие биты теряются, а старшие заполняются нулями |
&= | Упрощенная форма побито- вого оператора & с присваиванием | Команда вида A& A=A&B |
|= | Упрощенная форма побито- вого оператора | с присваиванием | Команда вида A|=B является эквивалентом команды A=A|B |
Оператор | Название | Пояснение |
^= | Упрощенная | Команда вида A^=B является эквивалентом команды |
форма побито- | ||
вого оператора ^ | A=A^B | |
с присваиванием | ||
>>= | Упрощенная | Команда вида A>>=B является эквивалентом команды |
форма побитово- | ||
го оператора >> | A=A>>B | |
с присваиванием | ||
<<= | Упрощенная | Команда вида A<<=B является эквивалентом команды |
форма побитово- | ||
го оператора << | A=A< | |
с присваиванием | ||
>>>= | Упрощенная | Команда вида A>>>=B является эквивалентом команды |
форма побитово- | ||
го оператора >>> | A=A>>>B | |
с присваиванием |
За редким исключением, побитовые операции используются в случаях, когда необходимо оптимизировать программу в отношении быстродействия.
Помимо перечисленных операторов, в Java есть единственный тернарный опе- ратор (у оператора три операнда). Формально оператор обозначается как?:. Синтаксис вызова этого оператора следующий:
условие?значение_1:значение_2
Первым операндом указывается условие - выражение, возвращающее в качестве значения логическое значение. Если значение выражения-условия равно true, в качестве значения тернарным оператором возвращается значение_1. Если зна- чением выражения-условия является false, тернарным оператором в качестве значения возвращается значение_2.
Несколько замечаний по поводу оператора присваивания (оператор =). В Java оператор присваивания возвращает значение. Команда вида x=y выполняется следующим образом. Сначала вычисляется выражение y, после чего это выра- жение приводится к типу переменной x и затем записывается в эту переменную. Благодаря тому, что, в отличие от других операторов с равными приоритетами, присваивание выполняется справа налево, в Java допустимыми являются ко- манды вида x=y=z. В этом случае значение переменной z присваивается сначала переменной y, а затем значение переменной y присваивается переменной x.
Еще одно замечание касается упрощенных форм операторов с присваиванием, то есть операторов вида op=. Хотя утверждалось, что команда вида A op=B эк- вивалента команде A=A op B, это не совсем так. При выполнении команды вида A op=B сначала вычисляется выражение A op B, затем полученное значение при- водится к типу переменной A и только после этого присваивается переменной A. Поскольку приведение к типу переменной A выполняется, фактически, явно, а в команде A=A op B приведение типов неявное, может проявиться разница
в использовании полной и упрощенной форм команд присваивания. Рассмо- трим простой пример:
// Правильно: a+=20;
// Неправильно: a=a+b;
В данном случае команда a+=20 является корректной, а команда a=a+b - нет. В первом случае литерал 20 типа int «насильственно» приводится к типу byte в силу особенностей оператора +=. Во втором случае результат вычисления вы- ражения a+b автоматически расширяется до типа int, а автоматическое приведе- ние типа int к типу byte запрещено.
Напоследок приведем в табл. 1.6 данные о приоритете различных операторов в Java.
Таблица 1.6. Приоритеты операторов в Java
Приоритет | Операторы |
Круглые скобки (), квадратные скобки и оператор «точка» | |
Инкремент ++, декремент --, отрицания ~ и! | |
Умножение *, деление / и вычисление остатка % | |
Сложение + и вычитание - | |
Побитовые сдвиги >>, << и >>> | |
Больше >, больше или равно >=, меньше или равно <= и меньше < | |
Равно == и неравно!= | |
Побитовое И & | |
Побитовое исключающее ИЛИ ^ | |
Побитовое ИЛИ | | |
Логическое И && | |
Логические ИЛИ || | |
Тернарный оператор?: | |
Присваивание = и сокращенные формы операторов вида op= |
Операторы равных приоритетов (за исключением присваивания) выполняются слева направо. В случаях когда возникают сомнения в приоритете операторов и последовательности вычисления выражений, рекомендуется использовать круглые скобки.