Back to Blog
Java

Java Compound Assignment Operators

java compound assignment operators: Explains how Java compound assignment operators work, including the implicit cast, single evaluation of the left operand, and overf...

java operatorsimplicit type conversiontype castingjava syntaxoperator evaluation
Diagram of a compound assignment operator merging an operation with an implicit cast into the target type.

Java compound assignment operators such as +=, -=, and *= combine an arithmetic or bitwise operation with assignment in a single expression. They look like a shorthand for x = x + value, but the Java Language Specification defines them with two behaviors that change the result in ways that are easy to miss: an implicit narrowing cast to the type of the left operand, and single evaluation of the left operand. Understanding both behaviors is what separates correct use from subtle bugs.

The Operator Set and Basic Syntax

Compound assignment operators exist for every binary arithmetic, bitwise, and shift operator. The general form is:

lhs op= rhs;

which is equivalent to:

lhs = (T) ((lhs) op (rhs));

where T is the type of lhs. The full set is:

OperatorOperation
+=addition
-=subtraction
*=multiplication
/=division
%=modulo
&=bitwise AND
`=`
^=bitwise XOR
<<=left shift
>>=signed right shift
>>>=unsigned right shift

The Implicit Cast That Changes Behavior

The most important difference between x = x + value and x += value is the hidden cast. Consider:

short s = 10; s = s + 1; // compile error: int cannot be converted to short

The expression s + 1 is an int because binary numeric promotion promotes short to int. Assigning it back to short without a cast is a compile error. Now the compound form:

short s = 10; s += 1; // compiles

This compiles because s += 1 is defined as s = (short)(s + 1). The compound assignment operator performs the cast automatically. That is convenient, but it also means overflow and truncation can be silently introduced.

Where the Cast Causes Silent Data Loss

The automatic cast does not check whether the value fits. If the result of the operation exceeds the range of the left operand's type, the value is truncated. For example:

byte b = 100; b += 28; // b becomes -128, not 128

The addition 100 + 28 produces 128, which does not fit in a byte. The implicit cast wraps the value to -128. The same operation written as b = (byte)(b + 28) shows the cast explicitly, but the compound form hides it. When the left operand is int or long, the same overflow behavior applies but is less surprising because the arithmetic itself overflows in the same way it would with a normal expression.

The Left Operand Is Evaluated Only Once

The second defining behavior is that the left operand is evaluated exactly once. This matters when the left side is not a simple variable. Consider an array element:

int[] arr = {10, 20}; int i = 0; arr[i++] += 5;

The expression arr[i++] is evaluated once, so i is incremented once and arr[0] receives 15. The expanded form arr[i++] = arr[i++] + 5 would evaluate i++ twice, incrementing i twice and reading from the wrong index. The same single-evaluation guarantee applies to method calls, field accesses, and any other expression that can appear on the left side of an assignment.

Compound Assignment with Bitwise and Shift Operators

The bitwise and shift forms follow the same rules. The cast applies to the result, and the left operand is evaluated once. A common use is toggling a flag:

int flags = 0b1010; flags |= 0b0100; // sets the third bit flags ^= 0b0001; // toggles the low bit

The shift forms also perform the cast. For byte and short operands, the shift amount is masked to the low five bits for int and low six bits for long, which is a property of the shift operator itself, not of the compound form.

Readability and Maintainability Tradeoffs

Compound assignment is more concise, but it can obscure the implicit cast and the single-evaluation guarantee. When the left operand is a simple local variable and the operation is a straightforward increment, the compound form is idiomatic and clear. When the left side is an array element, a field with complex access, or a type that can silently truncate, the expanded form with an explicit cast makes the behavior visible to the next reader. The choice is a maintainability decision: use the compound form where the shorthand matches the intent, and prefer the explicit form where the hidden cast would surprise someone reading the code.

java compound assignment operators: Practical Usage and Code | RYUSLOG DEV