Сложение в java. Арифметические операции. Целочисленные битовые операторы

Конспект лекций по Java. Занятие 4

(none) (none) ::
(none)
( В.Фесюнов )

Операции (operators) в языке Java

Большинство операций Java просты и интуитивно понятны. Это такие операции, как +, -, *, /, <,> и др. Операции имеют свой порядок выполнения и приоритеты. Так в выражении

сначала выполняется умножение, а потом сложение, поскольку приоритет у операции умножения выше, чем у операции сложения. В выражении

сначала вычисляется a + b, а потом от результата вычитается c, поскольку порядок выполнения этих операций слева направо.

Но операции Java имеют и свои особенности. Не вдаваясь в детальное описание простейших операций, остановимся на особенностях.

Начнем с присваивания . В отличии от ряда других языков программирования в Java присваивание — это не оператор, а операция. Семантику этой операции можно описать так.

  • Операция присваивания обозначается символом "=". Она вычисляет значение своего правого операнда и присваивает его левому операнду, а также выдает в качестве результата присвоенное значение. Это значение может быть использовано другими операциями. Последовательность из нескольких операций присваивания выполняется справа налево.

В простейшем случае все выглядит как обычно.

Здесь происходит именно то, что мы интуитивно подразумеваем, — вычисляется сумма a и b, результат заносится в x. Но вот два других примера.

В первом сначала 1 заносится в b, результатом операции является 1, потом этот результат заносится в a. Во втором примере вычисляется сумма a и b и результат теряется. Это бессмысленно, но синтаксически допустимо.

Операции сравнения

Это операции >, <, >=, <=, != и ==. Следует обратить внимание, что сравнение на равенство обозначается двумя знаками "=". Операндами этих операций могут быть арифметические данные, результат — типа boolean.

Операции инкремента, декремента

Это операции ++ и --. Так y++ (инкремент) является сокращенной записью y = y +1, аналогично и с операцией декремента (--).

Но с этими операциями есть одна тонкость. Они существуют в двух формах - префиксной (++y) и постфиксной (y++). Действие этих операций одно и то же — они увеличивают (операции декремента — уменьшают) свой операнд на 1, а вот результат у них разный. Префиксная форма в качестве результата выдает уже измененное на 1 значение операнда, а постфиксна -значение операнда до изменения.

A = 5; x = a++; y = ++a;

В этом фрагменте x получит значение 5, а y — 7.

Операция целочисленного деления

Нужно учитывать, что деление одного целого на другое выдает целое, причем не округляет, а отбрасывает дробную часть.

Остаток от деления (значение по модулю)

В Java имеется операция %, которая обозначает остаток от деления.

Расширенные операции присваивания

Кроме обычной операции "=" в Java существуют операции +=, -=, *=, /= и др. Это сокращенные записи. Так a += b полностью эквивалентна a = a + b. Аналогично и с другими такими операциями.

Логические операции

! — отрицание && — логическое "и" || — логическое "или"

Операнды этих операций должны быть типа boolean, результат — boolean. Операции && и || имеют одну особенность — их правый операнд может и не вычислиться, если результат уже известен по левому операнду. Так, если левый операнд операции && — ложь (false), то правый операнд вычисляться не будет, т.к. результат все равно — ложь.

Это свойство нужно учитывать, особенно тогда, когда правый операнд содержит вызов некоторой функции.

Побитовые логические операции

Это операции

& — побитовое "и" | — побитовое "или" ^ — побитовое "исключающее или" ~ — побитовое отрицание

Они выполняются для каждой пары битов своих операндов.

Операции сдвига

<< — сдвиг влево >> — сдвиг вправо >>> — беззнаковый сдвиг вправо

Эти операции сдвигают значение своего левого операнда на число бит, заданное правым операндом.

Условная операци

Это единственная тернарная операция, т.е. операция, имеющая три операнда. Соответственно, для нее используется не один знак операции, а два.

<условие> ? <выражение1> : < выражение2>

Если <условие> истинно, то результатом будет < выражение1>, иначе < выражение2>.

Например, "a < b ? a: b" вычисляет минимум из a и b.

Операция приведения типов

Это очень важная операция. По умолчанию все преобразования, которые могут привести к проблемам, в Java запрещены. Так, нельзя long-значение присвоить int-операнду. В тех случаях, когда это все же необходимо, нужно поставить явное преобразование типа.

Например, пусть метод f(...) выдает long.

int x = (int)f(10);

Здесь (int) — это операция преобразования типа. Операция преобразования типа обозначается при помощи имени типа, взятого в скобки.

Эта операция применима не только к базовым типам, но и к классам. Мы разберем это подробнее, когда будем рассматривать наследование.

Литералы (константы)

Арифметические

Примеры арифметических констант

10 - 010 — это 8 - 0123 — это 83 (1*64 + 2*8 + 3) - 0x10 — это 16 - 0x123 — это 291 (1*256 + 2*16 +3) - 1e5 — это 100000 - 1.23e-3 — это 0.00123

Для указания типа константы применяются суффиксы: l (или L) — long, f (или F) — float, d (или D) — double. Например,

1L — единица, но типа long.

Логические литералы

Логические литералы — это true (истина) и false (ложь)

Строковые литералы

Записываются в двойных кавычках, например

"это строка"

Символьные литералы

Записываются в апострофах, например "F", "ш".

В строковых и символьных литералах есть правила для записи спец. символов. Во-первых, есть набор предопределенных спец. символов. Это

- "\n" — конец строки (перевод строки) - "\r" — возврат каретки - "\t" — табуляция

и ряд других.

Во-вторых, можно явно записать код символа (нужно только знать его). Запись кода обычно выполняется в восьмеричной системе: "\001" — символ с кодом 1 и т.п.

Операторы (statements)

Оператор — выражение

Синтаксис

<выражение>;

Такой оператор состоит из одного выражения, в конце стоит ";". Его действие состоит в вычислении выражения, значение, вычисленное данным выражением, теряется. Т.е. обычно такое выражение содержит операцию присваивания, хотя это по синтаксису не обязательно.

A = 0; x = (a > b ? a: b); cnt++;

Условный оператор (if)

Синтаксис

If (<условие>) <оператор1>

Здесь <условие> — это логическое выражение, т.е. выражение, возвращающее true или false. Как видно из синтаксиса, часть else вляется необязательной. После if и после else стоит по одному оператору. Если нужно поместить туда несколько операторов, то нужно поставить блок . Блок начинается с "{" и заканчивается "}".

В Java принято блок ставить всегда, даже если после if или else стоит один оператор.

If (a > b) { x = a; } else { x = b; } if (flag) { flag = false; init(); }

В последнем примере flag — логическая переменная или поле, init() -метод, вызываемый, если флаг равен true (говорят, "если flag установлен").

Оператор return (уже рассматривали)

Оператор цикла по предусловию (while)

Синтаксис

While (<условие>) <оператор>

Как и в случае оператора if, в Java принято <оператор> заключать в фигурные скобки.

Int i = 0; while (more) { x /= 2; more = (++i < 10); }

В этом примере more должна быть логической переменной или полем, x — некоторой арифметической переменной или полем. Цикл выполняется 10 раз.

Оператор цикла по постусловию (do while)

Синтаксис

Do <оператор> while (<условие>);

Оператор цикла по постусловию отличается от оператора цикла по предусловию только тем, что в нем виток цикла выполняется всегда как минимум один раз, в то время как в операторе по предусловию может не быть ни одного витка цикла (если условие сразу ложно).

Int i = 0; do { x \= 2; more = (++i < 10); } while (more);

Оператор цикла "со счетчиком" (for)

Синтаксис

For (<инициализация>; <условие>; <инкремент>) <оператор>

Заголовок такого цикла содержит три выражения (в простейшем случае). Из наименования оператора можно понять, что он служит для организации цикла со счетчиком. Поэтому выражение <инициализация> выполняется один раз перед первым витком цикла. После каждого витка цикла выполняется выражение <инкремент>, а потом выражение <условие>. Последнее выражение должно быть логическим и служит для задания условия продолжения цикла. Т.е. пока оно истинно, витки цикла будут продолжаться.

Для удобства составления операторов цикла со счетчиком в данной конструкции введено множество расширений.

  • <инициализация> может быть не выражением, а описанием с инициализацией типа "int i = 0".
  • <инициализация> может быть списком выражений через запятую, например, "i = 0, r = 1" .
  • <инкремент> тоже может быть списком выражений, например, "i++, r*=2"
  • Все составляющие (<инициализация>, <условие> и <инкремент>) являются необязательными. Для выражения <условие> это означает, что условие считается всегда истинным (т.е. выход из цикла должен быть организован какими-то средствами внутри самого цикла).

Т.е. допустим и такой цикл (бесконечный цикл):

For (;;) { . . . }

For (int i = 0; i < 10; i++) x /=2;

Это самая "экономичная" реализация цикла из предыдущих примеров.

Операторы break и continue

В Java нет операторов goto. Как известно, goto приводит к появлению неструктурированных программ. Операторы break и continue являются структурированными аналогами goto.

Они могут применяться в циклах, а break еще и в операторе выбора (switch). Выполнение оператора break приводит к немедленному завершению цикла. Оператор continue вызывает окончание текущего витка цикла и начало нового. Проверка условия в этом случае все же выполняется, так что continue может вызвать и окончание цикла.

For (int i = 0; ;i++) { if (oddOnly && i%2 == 0) continue; y = (x + 1)/x; if (y — x < 0.001) break; x = y; }

Здесь oddOnly — логическая переменная. Если она установлена, то все витки цикла с четными номерами пропускаются с использованием оператора continue;

Условие окончания цикла в данном примере проверяется в середине цикла и, если оно выполнено, то цикл прекращается при помощи оператора break.

При вложенных циклах операторы break и continue могут относиться не только к тому циклу, в котором они расположены, но и к охватывающему циклу. Для этого охватывающий оператор цикла должен быть помечен меткой, которая должна быть указана в операторе break или continue. Например,

Lbl: while (...) { . . . for (...) { . . . if (...) break lbl; } . . . }

Здесь оператор break вызовет прекращение как цикла for, так и while.

Оператор выбора (switch)

Служит для организации выбора по некоторому значению одной из нескольких ветвей выполнения.

Синтаксис

Switch (<выражение>) { case <константа1>: <операторы1> case <константа2>: <операторы2> . . . }

Выражение должно выдавать целочисленное или символьное значение, константы должны быть того же типа, что и значение этого выражения.

Элементы "case <константа>:" являются метками перехода, если значение выражения совпадает с константой, то будет осуществлен переход на эту метку. Если значение выражения не совпадает ни с одной из констант, то все зависит от наличия фрагмента default. Если он есть, то переход происходит на метку default, если его нет, то весь оператор switch пропускается.

  • В операторе switch фрагменты case не образуют какие-либо блоки. Если после последнего оператора данного case-фрагмента стоит следующий case, то выполнение будет продолжено, начиная с первого оператора этого case-фрагмента.
  • В силу этого в операторе switch обычно применяется оператор break. Он ставится в конце каждого case-фрагмента.

Пример (файл SymbolTest.java)

Рассмотрим демонстрационную программу, в которой использованы операторы for и switch.

Эта программа генерирует случайным образом 100 символов латинского алфавита и классифицирует их как "гласные", "согласные" и "иногда гласные". В последнюю категорию отнесены символы "y" и "w".

Public class SymbolTest { public static void main(String args) { for (int i = 0; i < 100; i++) { char c = (char)(Math.random()*26 + "a"); System.out.print(c + ": "); switch (c) { case "a": case "e": case "i": case "o": case "u": System.out.println("гласная"); break; case "y": case "w": System.out.println("иногда гласная"); break; default: System.out.println("согласная"); } } } }

В данном примере есть несколько новых для нас элементов.

  • Используется метод random() класса Math. Посмотрим документацию по классу Math и разберемся, что он делает.
  • В операторе char c = (char)(Math.random()*26 + "a"); производится сложение арифметического значения с символом. При таком сложении в Java символ преобразуется в число, которое равно коду этого символа.
  • В операторе System.out.print(c + ": "); используется не println(...), а print(...). Метод print(...) отличается от println(...) только тем, что не переводит печать на новую строку, так что следующий оператор print(...) или println(...) продолжит печать в той же строке.

Следует также обратить внимание на фрагменты case. Формально здесь 7 таких фрагментов, но 5 из них не содержат никаких операторов. Так что, можно считать, что здесь 2 case-фрагмента, но каждый из них имеет несколько меток case.

Задание на дом

  • 1 Изменить SymbolTest.java так, чтобы количество генерируемых символов задавалось параметром вызова программы.
  • 2 Написать программу, которая в качестве параметров вызова принимает два числа - длины катетов прямоугольного треугольника, а в качестве результата печатает углы в градусах.


(none)

Большинство операций над примитивными типами выполняется не с помощью методов, а с помощью специальных символов, называемых знаком операции .

Операция присваивания

Присвоение переменной значения константы, другой переменной или выражения (переменных и/или констант, разделенных знаками операций), называется операцией присваивания и обозначается знаком "= ", например: x = 3 ; y = x; z = x; В Java допустимо многократное использование операции присваивания в одном выражении, например: x1 = x2 = x3 = 0 ; Эта операция выполняется справа налево, т.е. сначала переменной x3 присваивается значение 0 , затем переменной x2 присваивается значение переменной x3 (0), и, наконец, переменной x1 присваивается значение переменной x2 (0). Знаки операций, аргументами которых являются числа, разделяются на две категории: унарные (unary) знаки операций с одним аргументом и бинарные (binary) с двумя аргументами.

Унарные операции

В Java определены следующие унарные операции:
  • унарный минус " - " – меняет знак числа или выражения на противоположный;
  • унарный плюс " + " – не выполняет никаких действий над числом или выражением;
  • побитовое дополнение " ~ " (только для целых) – инвертирует все биты поля числа (меняет 0 на 1 и 1 на 0);
  • инкремент " ++ " (только для целых) – увеличивает значение переменной на 1;
  • декремент " -- " (только для целых) – уменьшает значение переменной на 1.
Примеры унарных операций " + " и " - ": int i = 3 , j, k; j= - i; // j = -3 k = + i; // k = 3 Пример операции побитового дополнения: int a = 15 ; int b; b = ~ a; // b = -16 Числа a и b являются числами типа int , т.е. представляются внутри компьютера как двоичные целые числа со знаком длиной 32 бита, поэтому двоичное представление чисел a и b будет выглядеть следующим образом: a = 00000000 00000000 00000000 00001111 b = 11111111 11111111 11111111 11110000 Как видно из этого представления, все нулевые биты в числе a изменены на единичные биты в числе b , а единичные биты в a изменены на нулевые биты. Десятичным представлением числа b будет –16 . Знаки операции инкремента и декремента могут размещаться как до, так и после переменной. Эти варианты называются соответственно префиксной и постфиксной записью этих операции. Знак операции в префиксной записи возвращает значение своего операнда после вычисления выражения. При постфиксной записи знак операции сначала воз­вращает значение своего операнда и только после этого вычисляет инкремент или декремент, например: int x = 1 , y, z; y = ++ x; z= x++ ; Переменная y будет присвоено значение 2 , поскольку сначала значение x будет увеличено на 1 , а затем результат будет присвоен переменной y . Переменной z будет присвоено значение 1 , поскольку сначала переменной z будет присвоено значение, а затем значение x будет увеличено на 1 . В обоих случаях новое значение переменной x будет равно 2 . Следует отметить, что в Java, в отличие от языка C, операции декремента и инкремента могут применяться и к вещественным переменным (типа float и double). Бинарные знаки операций подразделяются на операции с числовым результатом и операции сравнения, результатом которых является булевское значение.

Арифметические бинарные операции

В Java определены следующие арифметические бинарные операции :
  • сложение " + ";
  • вычитание " - ";
  • умножение " * ";
  • деление " / ";
  • вычисление остатка от деления целых чисел " % " (возвращает остаток от деления первого числа на второе, причем результат будет иметь тот же знак, что и делимое), например, результат операции 5%3 будет равен 2 , а результат операции (-7)%(-4) будет равен -3 . В Java операция может использоваться и для вещественных переменных (типа float или double).
Примеры бинарных арифметических операций: int x = 7 , x1, x2, x3, x4, x5; x1 = x + 10 ; // x1 = 17 x2 = x – 8 ; // x2 = -1 x3 = x2 * x; // x3 = -7 x4 = x/ 4 ; // x4 = 1 (при делении целых чисел // дробная часть отбрасывается) x5 = x% 4 // x5 = 3 (остаток от деления // 7 на 4)

Побитовые операции

  • Побитовые операции рассматривают исходные числовые значения как поля битов и выполняют над ними следующие действия:
  • установка бита в i -ой позиции поля результата в 1 , если оба бита в i -ых позициях операндов равны 1 , или в 0 в противном случае – побитовое И (" & ");
  • установка бита в i -ой позиции поля результата в 1 , если хотя бы один бит в i -ых позициях операндов равен 1 , или в 0 в противном случае – побитовое ИЛИ (" | ");
  • установка бита в i -ой позиции поля результата в 1 , если биты в i -ых позициях операндов не равны друг другу, или в 0 в противном случае – побитовое исключающее ИЛИ (" ^ ");
  • сдвиг влево битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом не меняется) – побитовый сдвиг влево с учетом знака " << ";
  • сдвиг вправо битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом не меняется) – побитовый сдвиг вправо с учетом знака " >> ";
  • сдвиг вправо битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом также сдвигается) – побитовый сдвиг вправо без учета знака " >>> ".
Примеры побитовых операций:
  1. Побитовое И

    int x = 112 ; int y = 94 ; int z; z = x & y; // z=80: 00000000 00000000 00000000 01010000
  2. Побитовое ИЛИ

    int x = 112 ; // x: 00000000 00000000 00000000 01110000 int y = 94 ; // y: 00000000 00000000 00000000 01011110 int z; z = x | y; // z = 126: 00000000 00000000 00000000 01111110
  3. Побитовое исключающее ИЛИ

    int x = 112 ; // x: 00000000 00000000 00000000 01110000 int y = 94 ; // y: 00000000 00000000 00000000 01011110 int z; z = x ^ y; // z = 46: 00000000 00000000 00000000 00101110
  4. Сдвиг влево с учетом знака

    int x = 31 , z; // x: 00000000 00000000 00000000 00011111 z = x << 2 ; // z = 124: 00000000 00000000 00000000 01111100
  5. Сдвиг вправо с учетом знака

    int x = - 17 , z; z = x >> 2 ; // z = -5: 11111111 11111111 11111111 11111011
  6. Сдвиг вправо без учета знака

    int x = - 17 , z; // x: 11111111 11111111 11111111 11101111 z = x >>> 2 ; // z = 1073741819 // z: 00111111 11111111 11111111 11111011

Комбинированные операции

В Java для бинарных арифметических операций можно использовать комбинированные (составные) знаки операций: идентификатор операция = выражение Это эквивалентно следующей операции: идентификатор = идентификатор операция выражение Примеры:
  1. Выражение x += b означает x = x + b .
  2. Выражение x -= b означает x = x - b .
  3. Выражение x *= b означает x = x * b .
  4. Выражение x /= b означает x = x / b .
  5. Выражение x %= b означает x = x % b .
  6. Выражение x &= b означает x = x & b .
  7. Выражение x |= b означает x = x | b .
  8. Выражение x ^= b означает x = x ^ b .
  9. Выражение x <<= b означает x = x << b .
  10. Выражение x >>= b означает x = x >> b .
  11. Выражение x >>>= b означает x = x >>> b .

Операции сравнения

В Java определены следующие операции сравнения:
  • " == " (равно), " != " (не равно),
  • " > " (больше), " >= " (больше или равно),
  • " < " (меньше) " <= " (меньше или равно)
имеют два операнда и возвращают булевское значение, соответствующее результату сравнения (false или true ). Следует обратить внимание, что при сравнении двух величин на равенство в Java, как и в C и в C++, используются символы "== " (два идущих без пробела друг за другом знака равенства), в отличие от оператора присваивания, в котором используется символ "= ". Использование символа " = " при сравнении двух величин либо вызывает ошибку при компиляции, либо приводит к неверному результату. Примеры операций сравнения: boolean isEqual, isNonEqual, isGreater, isGreaterOrEqual, isLess, isLessOrEqual; int x1 = 5 , x2 = 5 , x3 = 3 , x4 = 7 ; isEqual = x1 == x2; // isEqual = true isNonEqual = x1 != x2; // isNonEqual = false isGreater = x1 > x3; // isGreater = true // isGreaterOrEqual = true isGreaterOrEqual = x2 >= x3; isLess = x3 < x1; // isLess = true isLessOrEqual = x1 <= x3; // isLessOrEqual = false

Булевские операции

Булевские операции выполняются над булевскими переменными и их результатом также является значение типа boolean . В Java определены следующие булевские операции:
  • отрицание "!" – замена false на true , или наоборот;
  • операция И "&" – результат равен true , только, если оба операнда равны true , иначе результат – false ;
  • операция ИЛИ " | " – результат равен true , только, если хотя бы один из операндов равен true , иначе результат – false .
  • операция исключающее ИЛИ " ^ " – результат равен true , только, если операнды не равны друг другу, иначе результат – false .
Операции " & ", " | " и " ^ " можно, также как и соответствующие побитовые операции использовать в составных операциях присваивания: " &= ", " |= " и " ^= " Кроме того, к булевским операндам применимы операции " == " (равно) и " != " (не равно). Как видно из определения операций ИЛИ и И, операция ИЛИ приводит к результату true , когда первый операнд равен true , незави­симо от значения второго операнда, а операция И приводит к результату false , когда первый операнд равен false , независимо от значения второго операнда. В Java определены еще две булевские операции: вторые версии булевских операций И и ИЛИ, известные как укороченные (short-circuit) логические операции: укороченное И " && " и укороченное ИЛИ " || ". При использовании этих операций второй операнд вообще не будет вычисляться, что полезно в тех случаях, когда правильное функционирование правого операнда зависит от того, имеет ли левый операнд значение true или false . Примеры булевских операций: boolean isInRange, isValid, isNotValid, isEqual, isNotEqual; int x = 8 ; isInRange = x > 0 && x < 5 ; // isInRange = false isValid = x > 0 || x > 5 ; // isValid = true isNotValid = ! isValid; // isNotValid = false isEqual = isInRange == isValid; // isEqual = false // isNotEqual = true isNotEqual = isInRange != isValid

Условная операция

Условная операция записывается в форме выражение-1?выражение-2:выражение-3 . При этом сначала вычисляется выражение выражение-1 , которое должно дать булевское значение, а затем, если выражение-1 имеет значение true , вычисляется и возвращается выражение-2 как результат выполнения операции, либо (если выражение-1 имеет значение false), вычисляется и, как результат выполнения операции, возвращается выражение-3 . Пример условной операции: x= n> 1 ? 0 : 1 ; Переменной x будет присвоено значение 0 , если n>1 (выражение n>1 имеет значение true) или 1 , если n≤1 (выражение n>1 имеет значение false).

Старшинство операций

Операции в выражениях выполняются слева направо, однако, в соответствии со своим приоритетом. Так операции умножения в выражении y = x + z* 5 ; будет выполнена раньше, чем операция сложения, поскольку приоритет операции умножения выше, чем приоритет операции сложения. Приоритеты операций (в порядке уменьшения приоритета) в Java приведены в табл. 1.
Круглые скобки повышают старшинство операций, которые находятся внутри них. Так, если в приведенное выше выражение вставить скобки: y = (x + z) * 5 ; то сначала будет выполнена операция сложения, а затем операция умножения. Иногда скобки используют просто для того, чтобы сделать выражение более читаемым, например: (x > 1 ) && (x <= 5 ) ;

Преобразование и приведение типов при выполнении операций

В операции присваивания и арифметических выражениях могут использоваться литералы, переменные и выражения разных типов, например: double y; byte x; y = x + 5 ; В этом примере выполняется операция сложения переменной x типа byte и литерала 5 (типа int) и результат присваивается переменной y типа double . В Java, как и в языке C, преобразования типов при вычислении выражений могут выполняться автоматически, либо с помощью оператора приведения типа. Однако правила приведения типов несколько отличаются от правил языка C, и в целом являются более строгими, чем в языке C. При выполнении операции присваивания преобразование типов происходит автоматически, если происходит расширяющее преобразование (widening conversion) и два типа совместимы . Расширяющими преобразованиями являются преобразования byte ®short ®int ®long ®float ®double . Для расширяющих преобразований числовые типы, включая целый и с пла­вающей точкой, являются совместимыми друг с другом. Однако числовые типы не совместимы с типами char и boolean . Типы char и boolean не совмес­тимы также и друг с другом. В языке Java выполняется автоматическое преобразование типов также и при сохранении литеральной целочисленной константы (которая имеет по умолчанию тип int) в перемен­ных типа byte , short или long (однако если литерал имеет значение вне диапазона допустимых значений для данного типа, выдается сообщение об ошибке: возможная потеря точности). Если преобразование является сужающим (narrowing conversion), т. е. выполняется преобразование byte ¬ short ¬ char ¬ int ¬ long ¬ float ¬ double , то такое преобразование может привести к потере точности числа или к его искажению. Поэтому при сужающих преобразованиях при компиляции программы выводится диагностическое сообщение о несовместимости типов и файлы классов не создаются. Такое сообщение будет выдано и при попытке преобразование выражений типа byte или short в переменную типа char . Если все же необходимо выполнить такие преобразования, используется операция приведения (cast) типа, которая имеет следующий формат: (тип-преобразования ) значение , где тип-преобразования определяет тип, в который необходимо преобразовать заданное значение , например, в результате выполнения операторов: byte x = 71 ; char symbol = (char ) x; переменная symbol получит значение " G ". Если значение с плавающей точкой присваивается целому типу, то (если значение с плавающей точкой имеет дробную часть) при явном преобразовании типа происходит также усечение (truncation) числа. Так, в результате выполнения оператора int x = (int ) 77.85 ; переменная x получит значение 77 . Если же присваиваемое значение лежит вне диапазона типа-преобразования , то результатом преобразования будет остаток от деления значения на модуль диапазона присваиваемого типа (для чисел типа byte модуль диапазона будет равен 256 , для short – 65536 , для int – 4294967296 и для long – 18446744073709551616). Например, в результате выполнения оператора byte x = (byte ) 514 ; переменная x получит значение 2 . При преобразовании целых или вещественных чисел в данные типа char , преобразование в символ происходит, если исходное число лежит в диапазоне от 0 до 127, иначе символ получает значение " ? ". При выполнении арифметических и побитовых преобразований все значения byte и short , а также char расширяются до int , (при этом в вычислениях для char используется числовое значение кода символа) затем, если хотя бы один операнд имеет тип long , тип целого выражения расширяется до long . Если один из операндов имеет тип float , то тип полного вы­ражения расширяется до float , а если один из операндов имеет тип double , то тип результата будет double . Так, если объявлены переменные byte a, c; short b; то в выражении a + b* c – 15 L + 1.5F + 1.08 - 10 ; сначала, перед вычислением a + b*c значения переменных будут расширены до int , затем, поскольку константа 15 имеет тип long , перед вычитанием результат вычисления будет увеличен до long . После этого, поскольку литерал 1.5 имеет тип float перед сложением с этим литералом результат вычисления a + b*c – 15L будет расширен до float . Перед выполнением сложения с числом 1.08 результат предыдущих вычислений будет расширен до double (поскольку вещественные константы по умолчанию имеют тип double) и, наконец, перед выполнением последнего сложения литерал 10 (по умолчанию int) будет расширен до double . Таким образом, результат вычисления выражения будет иметь тип double . Автоматические расширения типов (особенно расширения short и byte до int) могут вызывать плохо распознаваемые ошибки во время компиляции. Например, в операторах: byte x = 30 , y = 5 ; x = x + y; перед выполнением сложения значение переменных x и y будет расширено до int , а затем при выполнении попытки присвоения результата вычисления типа int переменной типа byte будет выдано сообщение об ошибке. Чтобы этого избежать надо использовать во втором операторе явное преобразование типов: x = (byte ) (x + y) ; Выражение x + y необходимо заключит в скобки потому, что приоритет операции приведения типа, заключенной в скобки, выше, чем приоритет операции сложения. Кстати, если записать второй оператор в виде: x += y; то сообщения об ошибке не будет. Ссылка на перво

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;

Другой пример с тернарным оператором можете посмотреть .