1. Overview
In this tutorial, we’ll have a look at Java compound operators, their types and how Java evaluates them.
We’ll also explain how implicit casting works.
2. Compound Assignment Operators
An assignment operator is a binary operator that assigns the result of the right-hand side to the variable on the left-hand side. The simplest is the “=” assignment operator:
int x = 5;
This statement declares a new variable x, assigns x the value of 5 and returns 5.
Compound Assignment Operators are a shorter way to apply an arithmetic or bitwise operation and to assign the value of the operation to the variable on the left-hand side.
For example, the following two multiplication statements are equivalent, meaning a and b will have the same value:
int a = 3, b = 3, c = -2;
a = a * c; // Simple assignment operator
b *= c; // Compound assignment operator
It’s important to note that the variable on the left-hand of a compound assignment operator must be already declared. In other words, compound operators can’t be used to declare a new variable.
Like the “=” assignment operator, compound operators return the assigned result of the expression:
long x = 1;
long y = (x+=2);
Both x and y will hold the value 3.
The assignment (x+=2) does two things: first, it adds 2 to the value of the variable x, which becomes 3; second, it returns the value of the assignment, which is also 3.
3. Types of Compound Assignment Operators
Java supports 11 compound assignment operators. We can group these into arithmetic and bitwise operators.
Let’s go through the arithmetic operators and the operations they perform:
- Incrementation: +=
- Decrementation: -=
- Multiplication: *=
- Division: /=
- Modulus: %=
Then, we also have the bitwise operators:
- AND, binary: &=
- Exclusive OR, binary: ^=
- Inclusive OR, binary: |=
- Left Shift, binary: <<=
- Right Shift, binary: >>=
- Shift right zero fill: >>>=
Let’s have a look at a few examples of these operations:
// 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
As we can see here, the syntax to use these operators is consistent.
4. Evaluation of Compound Assignment Operations
There are two ways Java evaluates the compound operations.
First, when the left-hand operand is not an array, then Java will, in order:
- Verify the operand is a declared variable
- Save the value of the left-hand operand
- Evaluate the right-hand operand
- Perform the binary operation as indicated by the compound operator
- Convert the result of the binary operation to the type of the left-hand variable (implicit casting)
- Assign the converted result to the left-hand variable
Next, when the left-hand operand is an array, the steps to follow are a bit different:
- Verify the array expression on the left-hand side and throw a NullPointerException or ArrayIndexOutOfBoundsException if it’s incorrect
- Save the array element in the index
- Evaluate the right-hand operand
- Check if the array component selected is a primitive type or reference type and then continue with the same steps as the first list, as if the left-hand operand is a variable.
If any step of the evaluation fails, Java doesn’t continue to perform the following steps.
Let’s give some examples related to the evaluation of these operations to an array element:
int[] numbers = null;
// Trying Incrementation
numbers[2] += 5;
As we’d expect, this will throw a NullPointerException.
However, if we assign an initial value to the array:
int[] numbers = {0, 1};
// Trying Incrementation
numbers[2] += 5;
We would get rid of the NullPointerException, but we’d still get an ArrayIndexOutOfBoundsException, as the index used is not correct.
If we fix that, the operation will be completed successfully:
int[] numbers = {0, 1};
// Incrementation
numbers[1] += 5; // x is now 6
Finally, the x variable will be 6 at the end of the assignment.
5. Implicit Casting
One of the reasons compound operators are useful is that not only they provide a shorter way for operations, but also implicitly cast variables.
Formally, a compound assignment expression of the form:
E1 op= E2
is equivalent to:
E1 – (T)(E1 op E2)
where T is the type of E1.
Let’s consider the following example:
long number = 10;
int i = number;
i = i * number; // Does not compile
Let’s review why the last line won’t compile.
Java automatically promotes smaller data types to larger data ones, when they are together in an operation, but will throw an error when trying to convert from larger to smaller types.
So, first, i will be promoted to long and then the multiplication will give the result 10L. The long result would be assigned to i, which is an int, and this will throw an error.
This could be fixed with an explicit cast:
i = (int) i * number;
Java compound assignment operators are perfect in this case because they do an implicit casting:
i *= number;
This statement works just fine, casting the multiplication result to int and assigning the value to the left-hand side variable, i.
6. Conclusion
In this article, we looked at compound operators in Java, giving some examples and different types of them. We explained how Java evaluates these operations.
Finally, we also reviewed implicit casting, one of the reasons these shorthand operators are useful.
As always, all of the code snippets mentioned in this article can be found in our GitHub repository.