Перейти к основному содержимому

Операции

Арифметические операции​

  • + - операция сложения двух чисел:
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)

Арифметические операции с присвоением​

В языке Java предусмотрена сокращенная запись арифметических операций с присовением.

  • +=
c += b;    // переменной "c" присваивается результат сложения "c" и "b"
с = с + b; // равнозначная инструкция
  • -=
c -= b;    // переменной "c" присваивается результат вычитания "b" из "c"
с = с - b; // равнозначная инструкция
  • *=
c *= b;    // переменной "c" присваивается результат произведения "c" и "b"
с = с * b; // равнозначная инструкция
  • /=
c /= b;    // переменной "c" присваивается результат деления "c" на "b"
с = с / b; // равнозначная инструкция
  • %=
c %= b;    // переменной "c" присваивается остаток от деления "c" на "b"
с = с % b; // равнозначная инструкция

Инкрементация и декрементация​

Инкрементация - увеличение значения переменной на единицу.

Декрементация - уменьшение значения переменной на единицу.

Существуют два вида операций инкремента и декремента. Оба этих вида операций изменяют значение переменной на единицу. Их отличие проявляется только тогда, когда эти операции присутствуют в присваивании. В префиксной форме сначала изменяется значение переменной, и только лишь потом присваивается, а в постфиксной форме присваивается прежнее значение этой переменной, и лишь после данной операции оно изменяется на единицу.

Операции ++ и -- изменяют значение переменной, поэтому их нельзя применять к самим числам. Например, выражение 4++ считается недопустимым.

  • ++ (префиксный инкремент)

Предполагает увеличение переменной на единицу, например, z = ++y (вначале значение переменной y увеличивается на 1, а затем ее значение присваивается переменной z)

int a = 8;
int b = ++a; // Равнозначные инструкции: b = a + 1;
System.out.println(a); // 9
System.out.println(b); // 9
  • ++ (постфиксный инкремент)

Также представляет увеличение переменной на единицу, например, z = y++ (вначале значение переменной y присваивается переменной z, а потом значение переменной y увеличивается на 1)

int a = 8;
int b = a++; // Равнозначные инструкции: b = a; a = a + 1;
System.out.println(a); // 9
System.out.println(b); // 8
  • -- (префиксный декремент)

Уменьшение переменной на единицу, например, z = --y (вначале значение переменной y уменьшается на 1, а потом ее значение присваивается переменной z)

int a = 8;
int b = --a; // Равнозначные инструкции: b = a - 1;
System.out.println(a); // 7
System.out.println(b); // 7
  • -- (постфиксный декремент)

z = y-- (сначала значение переменной y присваивается переменной z, а затем значение переменной y уменьшается на 1)

int a = 8;
int b = a--; // Равнозначные инструкции: b = a; a = a - 1;
System.out.println(a); // 7
System.out.println(b); // 8

Условные выражения​

Условные выражения представляют собой некоторое условие и возвращают значение типа boolean, то есть значение true (если условие истинно), или значение false (если условие ложно).

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

В операциях сравнения сравниваются два операнда, и возвращается значение типа boolean - true, если выражение верно, и false, если выражение неверно.

  • == - сравнивает два операнда на равенство и возвращает true, если операнды равны, и false, если операнды не равны
int a = 10;
int b = 4;
boolean c = a == b; // false
boolean d = a == 10; // true
  • != - сравнивает два операнда и возвращает true, если операнды НЕ равны, и false, если операнды равны
int a = 10;
int b = 4;
boolean c = a != b; // true
boolean d = a != 10; // false
  • < (меньше чем) - возвращает true, если первый операнд меньше второго, иначе возвращает false
int a = 10;
int b = 4;
boolean c = a < b; // false
  • > (больше чем) - возвращает true, если первый операнд больше второго, иначе возвращает false
int a = 10;
int b = 4;
boolean c = a > b; // true
  • >= (больше или равно) - возвращает true, если первый операнд больше второго или равен второму, иначе возвращает false
boolean c = 10 >= 10; // true
boolean b = 10 >= 4; // true
boolean d = 10 >= 20; // false
  • <= (меньше или равно) - возвращает true, если первый операнд меньше второго или равен второму, иначе возвращает false
boolean c = 10 <= 10; // true
boolean b = 10 <= 4; // false
boolean d = 10 <= 20; // true

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

Также в Java есть логические операции, которые также представляют условие и возвращают true или false и обычно объединяют несколько операций сравнения. К логическим операциям относят следующие:

  • | (или)

c = a | b; (c равно true, если либо a, либо b (либо и a, и b) равны true, иначе c будет равно false)

  • & (и)

c = a & b; (c равно true, если и a, и b равны true, иначе c будет равно false)

  • ! (отрицание)

c = !b; (c равно true, если b равно false, иначе c будет равно false)

  • ^ (исключающее или)

c = a ^ b; (c равно true, если либо a, либо b (но не одновременно) равны true, иначе c будет равно false)

  • || (или)

c = a || b; (c равно true, если либо a, либо b (либо и a, и b) равны true, иначе c будет равно false)

  • && (и)

c = a && b; (c равно true, если и a, и b равны true, иначе c будет равно false)

Здесь две пары операций | и || (а также & и &&) выполняют похожие действия, однако же они не равнозначны.

Выражение c = a | b; будет вычислять сначала оба значения - a и b и на их основе выводить результат.

В выражении же c = a || b; вначале будет вычисляться значение a, и если оно равно true, то вычисление значения b уже смысла не имеет, так как у нас в любом случае уже c будет равно true. Значение b будет вычисляться только в том случае, если a равно false.

То же самое касается пары операций &/&&. В выражении c = a & b; будут вычисляться оба значения - a и b.

В выражении же c = a && b; сначала будет вычисляться значение a, и если оно равно false, то вычисление значения b уже не имеет смысла, так как значение c в любом случае равно false. Значение b будет вычисляться только в том случае, если a равно true.

Таким образом, операции || и && более удобны в вычислениях, позволяя сократить время на вычисление значения выражения.

Таблицы истинности​

  • Отрицание:
a!a
falsetrue
truefalse
  • И:
aba & b
falsefalsefalse
falsetruefalse
truefalsefalse
truetruetrue
  • Или:
aba || b
falsefalsefalse
falsetruetrue
truefalsetrue
truetruetrue
  • Исключающее или:
aba ^ b
falsefalsefalse
falsetruetrue
truefalsetrue
truetruefalse

Дополнительные материалы​

Преобразование числовых типов​

Каждый базовый тип данных занимает определенное количество байт памяти. Это накладывает ограничение на операции, в которые вовлечены различные типы данных.

int a = 4;
byte b = a; // Ошибка

В данном коде произойдёт ошибка. Хотя и тип byte, и тип int представляют целые числа. Более того, значение переменной a, которое присваивается переменной типа byte, вполне укладывается в диапазон значений для типа byte (от -128 до 127). Тем не менее происходит ошибка на этапе компиляции. Поскольку в данном случае присваиваются некоторые данные, которые занимают 4 байта, переменной, которая занимает всего один байт.

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

int a = 4;
byte b = (byte) a; // преобразование типов: от типа int к типу byte
System.out.println(b); // 4

Операция преобразования типов предполагает указание в скобках того типа, к которому надо преобразовать значение. Например, в случае операции (byte) a, идет преобразование данных типа int в тип byte. В итоге мы получим значение типа byte.

Автоматическое преобразование​

Стрелками на рисунке показано, какие преобразования типов могут выполняться автоматически. Пунктирными стрелками показаны автоматические преобразования с потерей точности.

Пример автоматического преобразования:

byte b = 7;
int d = b; // преобразование от byte к int

В данном случае значение типа byte, которое занимает в памяти 1 байт, расширяется до типа int, которое занимает 4 байта.

Автоматические преобразования представлены следующими цепочками:

byte -> short -> int -> long

int -> double

short -> float -> double

char -> int

Некоторые преобразования могут производиться автоматически между типами данных одинаковой разрядности или даже от типа данных с большей разрядностью к типа с меньшей разрядностью. Это следующие цепочки преобразований: int -> float, long -> float и long -> double. Они производятся без ошибок, но при преобразовании мы можем столкнуться с потерей информации.

Пример:

int a = 2147483647;
float b = a; // от типа int к типу float
System.out.println(b); // 2.14748365E9

Приведение типов​

Во всех остальных преобразованиях примитивных типов явным образом применяется операция привидения типов. Обычно это преобразования от типа с большей разрядностью к типу с меньшей разрядностью:

long a = 4;
int b = (int) a;

При применении привидения типов мы можем столкнуться с потерей данных. Например, в следующем коде у нас не возникнет никаких проблем:

int a = 5;
byte b = (byte) a;
System.out.println(b); // 5

Число 5 укладывается в диапазон значений типа byte, поэтому после привидения переменная b будет равна 5.

Но в следующем примере результатом будет число 2:

int a = 258;
byte b = (byte) a;
System.out.println(b); // 2

В данном случае число 258 вне диапазона для типа byte (от -128 до 127), поэтому произойдет усечение значения.

Почему результатом будет именно число 2? Число a, которое равно 258, в двоичном системе будет равно 00000000 00000000 00000001 00000010. Значения типа byte занимают в памяти только 8 бит. Поэтому двоичное представление числа int усекается до 8 правых разрядов, то есть 00000010, что в десятичной системе дает число 2.

При преобразовании значений с плавающей точкой к целочисленным значениям, происходит усечение дробной части:

double a = 56.9898;
int b = (int) a;

Здесь значение числа b будет равно 56, несмотря на то, что число 57 было бы ближе к 56.9898.

Преобразования при операциях​

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

  • если один из операндов операции относится к типу double, то и второй операнд преобразуется к типу double
  • если предыдущее условие не соблюдено, а один из операндов операции относится к типу float, то и второй операнд преобразуется к типу float
  • если предыдущие условия не соблюдены, один из операндов операции относится к типу long, то и второй операнд преобразуется к типу long
  • иначе все операнды операции преобразуются к типу int

Примеры преобразований:

int a = 3;
double b = 4.6;
double c = a + b;

Так как в операции участвует значение типа double, то и другое значение приводится к типу double и сумма двух значений a + b будет представлять тип double.

Другой пример:

byte a = 3;
short b = 4;
byte c = (byte) (a + b);

Две переменных типа byte и short (не double, float или long), поэтому при сложении они преобразуются к типу int, и их сумма a + b представляет значение типа int. Поэтому если затем мы присваиваем эту сумму переменной типа byte, то нам опять надо сделать преобразование типов к byte.

Если в операциях участвуют данные типа char, то они преобразуются в int:

int d = 'a' + 5;
System.out.println(d); // 102