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 хранилище .