Topic 23 of 119 2. Fundamentals of Java Programming Interactive Tutorial

Assignment in Java: Simple and Compound Assignment Operators

16 mins read Last updated: 22 Aug 2026 18,979 views

Direct Answer & Core Concept

The simple assignment operator `=` stores the value on its right into the variable on its left, and it is the one operator in Java that is right-to-left, so `a = b = c = 10` sets all three to 10. Every compound operator such as `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=` and `>>>=` is shorthand for a longer statement: `x += 5` means `x = x + 5`, with one crucial exception. The `+=` family performs an implicit narrowing cast back to the type of the left variable, which is why `byte b = 1; b += 2;` compiles while `b = b + 2;` is rejected as a possible lossy conversion. The price of that convenience is silent truncation and silent overflow, so a `byte` multiplied by 300 wraps to 44 and `Integer.MAX_VALUE += 1` becomes negative without any warning. Compound assignment also evaluates the left-hand target exactly once, which is what makes `arr[index()] += 5` safe. Assignment is right-associative and has the lowest precedence of any operator, and it cannot be used to assign to a `final` variable or to `array.length`.

Detailed Explanation & Mechanics

1. What Is an Assignment Operator

An assignment operator stores a value into a variable. The one you already use is =, called the simple assignment operator. It reads "put the value on the right into the box named on the left".

Main.java
Run Online
x = 25;
+-----------+ +---------+ | x |

Two ideas are bundled into that one symbol, and both cause confusion later.

  • It is a **store**, not a copy of the value itself. For int the value is genuinely copied. For an object you copy the reference, so both variables then point at the same object.
  • = is not "equals". That is ==. Writing = where you meant == is the single most common typo in Java, and the compiler usually catches it with a message like *unexpected type* or *not a statement*.

2. The Simple Assignment Operator

= is used in two places that look identical but are not quite the same thing.

Main.java
Run Online
int count = 5;
// DECLARATION and initialisation: a new variable
count = 6;
// ASSIGNMENT: storing into a variable that already exists

The first creates a variable and gives it a value in one step. The second replaces the value of a variable that already exists. From the compiler's point of view both are assignment, which is why the JLS calls = the simple assignment operator and treats the declaration form as a special case of it.

Main.java
Run Online
int a, b, c;
// declare three variables, all defaulting to 0
a = b = c = 10;
// assignment is right-to-left, so all three become 10
  • The variable must already be declared. Java has no dynamic creation, unlike Python.
  • The type must match. A String variable cannot be given an int, and an int cannot be given a String, with no implicit conversion between them.
  • A local variable must be initialised before it is read. The compiler will not let you use a local int before you assign it. Fields are different: they silently default to 0, false or null.

3. The Compound Assignment Operators

A compound operator does an operation and stores the result in one step. Each one is shorthand for a longer statement, with one important exception covered in the next section.

OperatorSame AsOperatorSame As
+=x = x + y&=x = x & y
-=x = x - y|=x = x | y
*=x = x * y^=x = x ^ y
/=x = x / y<<=x = x << y
%=x = x % y>>=x = x >> y
>>>= is the unsigned right shift, and it is the one compound operator with no everyday non-compound equivalent you write by handIt fills the vacated bits with zeros, so a negative int becomes a large positive value

+= has a second job that catches people out. If the variable is a String, the right-hand side is concatenated rather than added.

Main.java
Run Online
String s = "Hello";
s += ", ";
// s is now "Hello, "
s += "Java";
// s is now "Hello, Java"
int n = 5;
n += 1;
// n is now 6, real addition

String concatenation is covered in detail in the String topic, but the rule to remember here is simply: if the left variable is a String, += means append.

4. The Rule That Makes b += 2 Legal

This is the single most tested fact about assignment in Java, and the original version of this page stated it in a way that was true but easy to misread. Here is the precise behaviour.

Main.java
Run Online
byte b = 1;
b = b + 2;
// ERROR: incompatible types: possible lossy conversion from int to byte
b += 2;
// FINE: b is 3

The two lines look identical but behave differently, and here is why.

```text
b = b + 2

1. b is promoted to int (every byte becomes an int for arithmetic)

b : byte --> 1 (int)

2. 1 + 2 is computed as int -> 3 (int)

3. an int cannot go into a byte without losing information

so the compiler refuses ERROR: possible lossy conversion

b += 2

1. b is promoted to int, added, giving an int -> 3 (int)

2. the compiler inserts a cast BACK to byte for you

(byte)(b + 2) -> 3 (byte) no error, because the cast was automatic
Main.java
Run Online
The cast is really there. `javap -c` on `b += 2` shows the arithmetic happening as `int` and then a narrowing `i2b` instruction to squeeze the result back into the byte.
java public class Cast { public static void main(String[] args) { byte b = 1; b += 2; // compiled as: iadd then i2b } } text 0: iconst_1 1: istore_1 2: iload_1 b becomes an int 3: iconst_2 4: iadd 1 + 2 = 3, as an int 5: i2b narrow 3 back to a byte <-- the implicit cast 6: istore_1 ``

This applies to +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, |= and ^=` alike. It is the reason compound assignment is not simply a shorthand.

5. The Bill for That Convenience: Silent Truncation

Because the cast is automatic, nothing warns you when the result does not fit. Java narrows by discarding digits, and it does so without any complaint at all.

Main.java
Run Online
public class Truncation {
    public static void main(String[] args) {
        byte c = 1;
        c *= 300;
        // 1 * 300 = 300, which does not fit in a byte
        System.out.println("byte c = 1; c *= 300;  -> c = " + c);
        int i = 1;
        i += 2.7;
        // 1 + 2.7 = 3.7, truncated to 3
        System.out.println("int i = 1; i += 2.7;    -> i = " + i);
        int x = 5;
        x /= 2.0;
        // a double on the right, an int on the left
        System.out.println("int x = 5; x /= 2.0;    -> x = " + x);
        short s = 32767;
        s += 1;
        // overflow wraps silently
        System.out.println("short 32767 + 1         -> s = " + s);
        int big = Integer.MAX_VALUE;
        big += 1;
        System.out.println("Integer.MAX_VALUE + 1  -> " + big);
    }
}

The real output:

Main.java
Run Online
byte c = 1;
c *= 300;
-> c = 44 int i = 1;
i += 2.7;
-> i = 3 int x = 5;
x /= 2.0;
-> x = 2 short 32767 + 1 -> s = -32768 Integer.MAX_VALUE + 1 -> -2147483648

Line by line, these are the rules:

  • c *= 300 computes 300, which does not fit in a byte, so it wraps to 300 minus 256, which is 44.
  • i += 2.7 promotes to double, adds to get 3.7, then casts back to int and truncates towards zero, giving 3. The .7 is simply discarded.
  • x /= 2.0 divides as a double to get 2.5, then narrows to int and truncates to 2. Had you written x /= 2 the result would also be 2, but for a different reason.
  • Adding 1 to short overflows, and adding 1 to Integer.MAX_VALUE overflows a 32-bit int. Both wrap silently. Overflow is **never** an exception in Java; it just produces a wrong number.

If silent truncation is a real risk, use Math.toIntExact or do the arithmetic in a wider type on purpose:

Main.java
Run Online
long count = 5_000_000_000L;
// 5 billion, far past the int range
int silently =(int) count;
// legal cast, silently gives 705032704
System.out.println("(int) count = " + silently);
// a wrong number, no warning
int safe = Math.toIntExact(count);
// throws ArithmeticException
Main.java
Run Online
(int) count = 705032704 Math.toIntExact throws: ArithmeticException

The same idea exists for long in Math.addExact and Math.multiplyExact, and both are worth reaching for whenever a number comes from outside your program.

6. The Left Side Is Evaluated Only Once

x += y is not simply a rewrite into x = x + y when the left side is an array element. Java evaluates the target once, then both reads and writes that same location. That is why this is safe and the naive rewrite is not.

Main.java
Run Online
public class EvaluatedOnce {
    static int[] values = {
        10, 20, 30
    };
    static int index = 1;
    public static void main(String[] args) {
        values[index] += 5;
        // 20 becomes 25
        System.out.println("values[1] is now " + values[1]);
        System.out.println("index is now " + index);
    }
}

The rule matters when the index is a method call or any expression with a side effect, because the value is computed exactly once.

Main.java
Run Online
public class Once {
    static int[] a = {
        10, 20, 30
    };
    static int calls = 0;
    static int idx() {
        calls++;
        return 1;
    } public static void main(String[] args) {
        a[idx()] += 5;
        // idx() is called exactly ONCE
        System.out.println("a[1] = " + a[1] + ", idx() called " + calls + " time(s)");
    }
}
Main.java
Run Online
a[1] = 25, idx() called 1 time(s)

If you rewrote this by hand as a[idx()] = a[idx()] + 5; then idx() would run twice, which matters whenever it costs money, logs something, or returns a different value each time.

7. Assignment Is Right-Associative and Lowest Precedence

Assignment chains group from the right. The expression a = b = c = 10 means "assign 10 to c, then to b, then to a".

Main.java
Run Online
a = b = c = 10 step 1: c = 10 step 2: b =(c = 10) b becomes 10 step 3: a =(b = c = 10) a becomes 10 all three end up as 10

= has the **lowest precedence** of any Java operator, so everything to the right is grouped before the assignment happens.

Main.java
Run Online
int m, n;
m = n = 2 + 3 * 4;
// * first: 2 + 12 = 14, then m and n both become 14

This is not (2 + 3) * 4. If you want the sum first you must parenthesise it, which is exactly why a calculator that forgets its brackets gives the wrong answer.

Because an assignment is itself an expression, it has a value, and you can use that value.

Main.java
Run Online
int total = 0;
int doubled =(total = 21) * 2;
// total becomes 21 first, then 21 * 2 = 42
  • The value of a = b is the value that was stored.
  • In C and C++ the value of an assignment is a constant you cannot assign to. In Java it is a normal variable, so a = b = c is normal code, not a trick.
  • Assignment and == are easy to confuse, and the mistake produces confusing errors such as *unexpected type*.

8. The Bitwise and Shift Compound Operators

The bitwise family has compound forms too, and they follow the same "operate then store" rule as arithmetic.

Main.java
Run Online
public class BitwiseAssign {
    public static void main(String[] args) {
        int x = 5;
        x >= 2;
        System.out.println("-8 >>= 2   -> " + y);
        // -2, keeps the sign
        int z = -1;
        z >>>= 1;
        System.out.println("-1 >>>= 1  -> " + z);
        // 2147483647, no sign
        System.out.println("            (>>> fills with zeros, so a negative int becomes large positive)");
        int w = 12;
        w &= 10;
        System.out.println("12 &= 10   -> " + w);
        // 8   1100 & 1010
        int v = 12;
        v |= 3;
        System.out.println("12 |= 3    -> " + v);
        // 15  1100 | 0011
        int u = 12;
        u ^= 10;
        System.out.println("12 ^= 10   -> " + u);
        // 6   1100 ^ 1010
    }
}

&=, |= and ^= also work on booleans, where they mean and, or and xor.

Main.java
Run Online
boolean p = true, q = false;
p &= q;
System.out.println("true &= false  -> " + p);
// false
p |= q;
System.out.println("false |= false -> " + p);
// false
p ^= true;
System.out.println("false ^= true  -> " + p);
// true

Note the two right shifts. >>= keeps the sign bit, so -8 becomes -2, while >>>= shifts in zeros, so -1 becomes 2147483647. The full bitwise story is in the bitwise computing topic.

9. What You Cannot Assign To

Not everything on the left of = is a variable, and Java rejects several things that look assignable.

Main.java
Run Online
final int f = 1;
f = 2;
// ERROR: cannot assign a value to final variable f
f += 1;
// ERROR: same thing, += is an assignment too
int[] n = {
    1, 2
};
n.length = 5;
// ERROR: cannot assign a value to final variable length
  • A final variable cannot be assigned after its initial assignment, whether you use = or a compound operator. Both are assignments as far as the compiler is concerned.
  • array.length is final by design, so it can never be changed.
  • Method call results, literals and the result of an expression are values, not places to store things, so they cannot be assigned to.

Assignment to a field, a method parameter or an array element is perfectly legal, and this is worth contrasting with Topic 20, where a note claimed that a final variable could still be "reassigned" by writing discount = discount - 1. It cannot. That line is a reassignment, and if discount is final the compiler rejects it. The same topic's snippet called that line "not a reassignment", which is simply wrong.

Main.java
Run Online
public class FinalIsFinal {
    public static void main(String[] args) {
        final int discount = 10;
        // discount = 20;                 // ERROR: final cannot be reassigned
        // discount = discount - 1;       // ERROR: still a reassignment
        int price = 100;
        // not final, so this is fine
        price = price - 1;
        // a reassignment, and perfectly legal
        System.out.println("price = " + price);
    }
}

10. Common Assignment Mistakes

What You WroteWhat HappensFix
x == y = 3Compiler error: unexpected type= assigns, == compares
int a == 5;Compares instead of declaringint a = 5;
byte b; b = b + 1;Lossy conversion from int to byteUse b += 1
int n = 0; n++; then using n as a count that overflowedSilent overflow, negative valueUse long or Math.addExact
arr[i] += 5 rewritten as arr[i] = arr[i] + 5Index expression runs twiceKeep +=, evaluate once
Assigning to arr.lengthCompiler error: final variable lengthResize with Arrays.copyOf
Assigning to a final variableCompiler error: final variableRemove the final
String s = "5"; s += 1; expecting 6You get the string "51"Parse first, then add
Reading a local before assigning itCompiler error: variable might not be initialisedGive it a value first
Reading a field before assigning itNo error, you silently get 0, false or nullInitialise fields explicitly

11. Assignment Cheat Sheet

QuestionAnswer
Simple assignment operator=
Arithmetic compound operators+= -= *= /= %=
Bitwise compound operators&= |= ^=
Shift compound operators<<= >>= >>>=
Does b += 2 work on a byteYes, via an implicit cast back to byte
Does b = b + 2 work on a byteNo, lossy conversion from int to byte
What does c *= 300 give for byte c = 144, silent wrap with no warning
What does i += 2.7 give for int i = 13, the fraction is truncated
Associativity of =Right to left, so chains work
Precedence of =Lowest of any Java operator
Is an assignment an expressionYes, and it has the stored value
How many times is the left side evaluatedExactly once
= versus ==Assign versus compare
Overflow behaviourSilent wrap, never an exception
Can you assign to a final variableNo, with = or any compound form
Can you assign to array.lengthNo, it is final
+= on a StringConcatenation, not addition

Assignment looks like one operator but is really two families. The simple = stores a value and has the lowest precedence in the language, while the compound operators are shorthands that quietly insert a cast back to the left-hand type. That cast is the reason b += 2 compiles when b = b + 2 does not, and it is also the reason a byte can wrap to 44 and an int can overflow without a single warning.

Runnable Code Example: Assignment in Java

Java 17+
Main.java
Run Online
public class AssignmentDemo {
    public static void main(String[] args) {
        // ---------- simple assignment ----------
        int x = 20;
        // declaration and initialisation in one step
        System.out.println("x starts at " + x);
        x = 30;
        // plain reassignment, the simplest assignment there is
        System.out.println("after x = 30, x is " + x);
        // ---------- every arithmetic compound operator ----------
        int y = 20;
        y += 5;
        // y = y + 5   -> 25
        y -= 3;
        // y = y - 3   -> 22
        y *= 2;
        // y = y * 2   -> 44
        y /= 4;
        // y = y / 4   -> 11
        y %= 4;
        // y = y % 4   ->  3
        System.out.println("after += -= *= /= %=, y is " + y);
        // ---------- the implicit cast that makes b += 2 legal ----------
        byte b = 10;
        b += 5;
        // compiles: this is really (byte)(b + 5)
        System.out.println("byte b = 10; b += 5 gives " + b);
        // ---------- string += is concatenation, not addition ----------
        String greeting = "Hello";
        greeting += ", ";
        // a String on the right, so it appends
        greeting += "Java";
        System.out.println(greeting);
        // ---------- right-to-left chaining ----------
        int a, c, d;
        a = c = d = 7;
        // all three end up as 7
        System.out.println("a = c = d = 7 gives a=" + a + " c=" + c + " d=" + d);
        // ---------- assignment is an expression, so it has a value ----------
        int total = 0;
        int doubled =(total = 21) * 2;
        // total becomes 21 first
        System.out.println("int doubled = (total = 21) * 2 gives " + doubled);
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

What is the difference between = and ==?

= is the assignment operator and stores the value on its right into the variable on its left. == is a comparison operator that asks whether two values are equal and produces a boolean. Swapping them is the most common Java typo and usually produces a compiler error such as "unexpected type".
Q2

Why does byte b = 1; b += 2; compile when b = b + 2; does not?

Every byte is promoted to int for arithmetic, so b + 2 is an int, and an int cannot be assigned to a byte without a cast because that would be a lossy conversion. The compound operator b += 2 is defined by the JLS as a cast to the type of the variable, so the compiler inserts (byte)(b + 2) automatically. You can see the narrowing i2b instruction in the bytecode.
Q3

What is the associativity of the assignment operator, and what does a = b = c = 10 do?

Assignment is right-associative, so the expression is grouped as a = (b = (c = 10)). The value 10 is stored into c first, then into b, then into a, leaving all three as 10.
Q4

What is the precedence of = compared with other operators?

It is the lowest of any Java operator, so everything to the right is evaluated first. In m = n = 2 + 3 * 4, multiplication happens before addition, giving 14, not 20. That is why an expression without brackets can give a different answer than you expect.
Q5

Is an assignment an expression in Java?

Yes, and that is a difference from C and C++. An assignment produces the value that was stored, so you can write int doubled = (total = 21) * 2, which sets total to 21 and doubled to 42. In C the value of an assignment is a constant that cannot be assigned to.
Q6

How many times is the left-hand side evaluated in a += b?

Exactly once. Java evaluates the target location first and then both reads from and writes to that same location. This matters for expressions like arr[index()] += 5, where rewriting it as arr[index()] = arr[index()] + 5 would call index() twice, with any side effects or cost that implies.
Q7

What happens with int i = 1; i += 2.7;?

The int is promoted to double, the addition produces 3.7, and the result is cast back to int, truncating towards zero, so i becomes 3. The fractional part is discarded silently with no warning, which is the main risk of compound assignment on a wider right-hand type.
Q8

Does Java throw an exception on integer overflow?

No. Arithmetic overflow wraps silently in both int and long, so Integer.MAX_VALUE + 1 becomes Integer.MIN_VALUE. Use Math.addExact, Math.multiplyExact or Math.toIntExact when you want an ArithmeticException instead of a wrong number.
Q9

Can you use a compound assignment operator on a final variable?

No. Any assignment, whether = or +=, is an assignment as far as the compiler is concerned, so assigning to a final variable after its initialisation is a compile error. Note that writing x = x - 1 is still a reassignment and is rejected, even though the variable appears on both sides.
Q10

Why is arr.length = 5 not allowed?

Every array has a final length field set when the array is created, so it cannot be changed. To change an array's size you must create a new one, for example int[] bigger = Arrays.copyOf(arr, 5).
Q11

What does += do when the left variable is a String?

It concatenates rather than adds, because the right-hand value is converted to text first. So String s = "5"; s += 1; produces the string "51", not the number 6. You must parse the string to a number first if you want arithmetic.
Q12

Why is a local variable required to be initialised while a field is not?

The compiler can check every path through a method, so it rejects reading a local variable that might not have been assigned, which prevents a whole class of bugs. Fields can be set by initialisers, static blocks, constructors or reflection, so the compiler cannot prove their value and gives them the default of 0, false or null. The practical advice is to initialise fields yourself rather than relying on the default.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Prefer compound assignment such as += and *= over repeating the variable name, because it is shorter, it evaluates the left-hand target exactly once, and it is the only form that compiles for narrower types like byte and short. Just be aware that the implicit cast is silent, so when a value could fall outside the range of the variable, do the arithmetic in a wider type on purpose or use Math.addExact and Math.toIntExact so an overflow becomes an exception rather than a wrong number. Do not use compound assignment to save keystrokes on a bitmask unless the bitwise shorthand is genuinely clearer, since x &= FLAG and x = x & FLAG are almost equally readable and the expanded form is easier to grep and debug. Never rely on the default value of a field, because 0, false and null are a common source of bugs that the compiler cannot warn you about; initialise fields explicitly. Remember that overflow in int and long wraps silently and is never an exception, so any arithmetic on money, byte counts or anything read from a file deserves a wider type and a deliberate decision. And keep the two equals signs apart, because x = y and x == y look almost identical and mean completely different things.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.