Составные операторы Java

1. Обзор

В этом руководстве мы рассмотрим составные операторы Java, их типы и то, как Java их оценивает.

Мы также объясним, как работает неявное приведение.

2. Составные операторы присваивания

Оператор присваивания - это бинарный оператор, который присваивает результат с правой стороны переменной с левой стороны. Самым простым является оператор присваивания «=» :

int x = 5;

Этот оператор объявляет новую переменную x , присваивает x значение 5 и возвращает 5 .

  • Составные операторы присваивания являются более коротким способом применения арифметической или побитовой операции и назначения значения операции переменной с левой стороны. **

Например, следующие два оператора умножения эквивалентны, означая, что a и b будут иметь одинаковое значение:

int a = 3, b = 3, c = -2;
a = a **  c;//Simple assignment operator
b ** = c;//Compound assignment operator

Важно отметить, что переменная слева от составного оператора присваивания должна быть уже объявлена. Другими словами, составные операторы не могут использоваться для объявления новой переменной.

Как и оператор присваивания «=», составные операторы возвращают присвоенный результат выражения:

long x = 1;
long y = (x+=2);

И x , и y будут содержать значение 3 .

Присвоение (x = 2) делает две вещи: во-первых, оно добавляет 2 к значению переменной x , которое становится 3; во-вторых, оно возвращает значение присваивания, которое также 3 .

3. Типы составных операторов присваивания

Java поддерживает 11 составных операторов присваивания. Мы можем сгруппировать их в арифметические и побитовые операторы.

Давайте рассмотрим арифметические операторы и операции, которые они выполняют:

  • Увеличение: =

  • Уменьшение: - =

  • Умножение: ** =

  • Отдел: /=

  • Модуль: % =

Тогда у нас также есть побитовые операторы:

  • И, бинарный: __

  • Исключительно ИЛИ, бинарный: ^ =

  • Включая ИЛИ, двоичный код: | =

  • Сдвиг влево, двоичный: << =

  • Сдвиг вправо, двоичный код: >> =

  • Сдвиг вправо, заполнение нулями: >>> =

Давайте посмотрим на несколько примеров этих операций:

----//Simple assignment
int x = 5;//x is 5
//Incrementation
x += 5;//x is 10
//Decrementation
x -= 2;//x is 8
//Multiplication
x ** = 2;//x is 16
//Modulus
x %= 3;//x is 1
//Binary AND
x &= 4;//x is 0
//Binary exclusive OR
x ^= 4;//x is 4
//Binary inclusive OR
x |= 8;//x is 12
----

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

4. Оценка составных операций присвоения

Есть два способа, которыми Java оценивает составные операции.

Во-первых, когда левый операнд не является массивом, тогда Java будет в следующем порядке:

, Убедитесь, что операнд является объявленной переменной

, Сохранить значение левого операнда

, Оценить правый операнд

, Выполните двоичную операцию, как указано составным оператором

, Преобразовать результат двоичной операции в тип

левая переменная (неявное приведение) , Присвойте преобразованный результат левой переменной

Далее, когда левый операнд является массивом, шаги, которые нужно выполнить, немного отличаются:

, Проверьте выражение массива с левой стороны и бросьте

NullPointerException или ArrayIndexOutOfBoundsException , если это некорректный , Сохранить элемент массива в индексе

, Оценить правый операнд

, Проверьте, является ли выбранный компонент массива примитивным типом или ссылкой

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

Если какой-либо шаг оценки завершается неудачно, Java не продолжает выполнять следующие шаги.

  • Давайте приведем несколько примеров, связанных с оценкой этих операций для элемента массива: **

int[]numbers = null;
//Trying Incrementation
numbers[2]+= 5;

Как и следовало ожидать, это вызовет исключение NullPointerException .

Однако, если мы присвоим начальное значение массиву:

int[]numbers = {0, 1};
//Trying Incrementation
numbers[2]+= 5;

Мы бы избавились от NullPointerException, но мы все равно получили бы ArrayIndexOutOfBoundsException , так как используемый индекс неверен.

Если мы исправим это, операция будет успешно завершена:

int[]numbers = {0, 1};
//Incrementation
numbers[1]+= 5;//x is now 6

Наконец, переменная x будет 6 в конце назначения.

5. Неявное кастинг

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

Формально составное выражение присваивания формы:

E1 op = E2

эквивалентно:

E1 - (T) (E1 op E2)

где T - это тип E1 .

Давайте рассмотрим следующий пример:

long number = 10;
int i = number;
i = i **  number;//Does not compile

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

Java автоматически продвигает меньшие типы данных к большим, когда они вместе в операции, но выдаст ошибку при попытке преобразования из больших в меньшие типы

Итак, сначала i будет повышен до long , а затем умножение даст результат 10L. Длинный результат будет присвоен i , который является int , и это вызовет ошибку.

Это можно исправить с помощью явного приведения:

i = (int) i **  number;
  • Составные операторы присваивания Java идеально подходят в этом случае, поскольку они выполняют неявное приведение

i ** = number;

Этот оператор работает отлично, приводя результат умножения к int и присваивая значение левой переменной i .

6. Заключение

В этой статье мы рассмотрели составные операторы в Java, приведя несколько примеров и различные их типы. Мы объяснили, как Java оценивает эти операции.

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

Как всегда, все фрагменты кода, упомянутые в этой статье, можно найти в нашем GitHub хранилище .