Skip to lesson
CodeLangs AISoftware Training Institute
Java Operators and Expressions

Chapter 5 · Java Expressions

Java Operators and Expressions

Master Java operators and expressions, including arithmetic and unary operators, increment and decrement, assignment, comparison, short-circuit logic, bitwise and shift operations, ternary expressions, instanceof, precedence, associativity, and evaluation order.

  • 7,727words
  • 36min read
  • 20quiz items
  • 21practice tools

This chapter covers Arithmetic Operators, Unary Operators, Increment/Decrement, Assignment and Compound Assignment, Relational and Equality Operators, Logical and Short-Circuit Operators, Bitwise and Shift Operators, the Ternary Operator, instanceof, Operator Precedence, Operator Associativity, Expression Evaluation, and Short-Circuit Evaluation, exactly as defined in the supplied chapter scope.


Before We Touch an Operator, Understand the Problem#

You already know that a Java program stores information in variables.

For example:

Java
int price = 100;
int quantity = 3;

At this moment Java knows two values:

Output
price    → 100
quantity → 3

But storing data alone is not enough.

A real program must do something with that data.

Suppose we are building an online shopping application.

We may need to:

  • calculate the total price
  • check whether stock is available
  • compare two prices
  • increase quantity
  • apply a discount
  • check whether a user is eligible for an offer
  • manipulate binary flags
  • choose one value depending on a condition

So the next question is:

How do we tell Java to perform operations on values?

Java provides operators for this purpose.


1. What Is an Operator?#

An operator is a symbol that tells Java to perform a specific operation on one or more values.

For example:

Java
int total = 100 + 50;

Here:

Output
100 + 50

contains three parts:

Output
100  → operand
+    → operator
50   → operand

The + operator tells Java:

Add the left operand and the right operand.

The result is:

Output
150

Operator vs Operand#

Consider:

Java
int result = a * b;

Here:

PartMeaning
aOperand
*Operator
bOperand
a * bExpression
result = a * bAssignment expression

An operand is the value on which an operator works.

An operator may work on:

  • one operand
  • two operands
  • three operands

This leads us to an important classification.


2. Operators Based on Number of Operands#

Unary Operator#

Works on one operand.

Example:

Java
int x = 10;
x++;

++ works on one variable.


Binary Operator#

Works on two operands.

Example:

Java
int sum = 10 + 20;

+ works on 10 and 20.


Ternary Operator#

Works on three operands.

Example:

Java
int max = a > b ? a : b;

Java's conditional ?: operator is commonly called the ternary operator.


3. What Is an Expression?#

We have already used the word expression several times.

Before going further, it must be clear.

An expression is a combination of values, variables, operators, and sometimes method calls that Java evaluates to produce a value.

Example:

Java
price * quantity

If:

Java
price = 100;
quantity = 3;

then:

Java
price * quantity

evaluates to:

Output
300

Another expression:

Java
age >= 18

produces:

Output
true

Another:

Java
salary > 50000 && experience >= 3

also produces a boolean value.

So expressions are everywhere in Java.


4. Arithmetic Operators#

Imagine that we are implementing a billing system.

We need to:

Output
Add prices
Subtract discounts
Multiply price × quantity
Divide totals
Find remainders

Java therefore provides arithmetic operators.

OperatorMeaning
+Addition
-Subtraction
*Multiplication
/Division
%Remainder

Addition Operator +#

Java
public class AdditionDemo {
    public static void main(String[] args) {
        int first = 20;
        int second = 10;
        int result = first + second;

        System.out.println(result);
    }
}

Output:

Output
30

Execution:

Output
first  = 20
second = 10

20 + 10
   ↓
  30

5. + Has Two Important Roles#

There is something special about +.

With numeric values:

Java
10 + 20

it performs addition.

With a String:

Java
"Java" + " Developer"

it performs String concatenation.

Concatenation means joining values together.

Example:

Java
public class ConcatenationDemo {
    public static void main(String[] args) {
        String firstName = "Amit";
        String lastName = "Patil";

        String fullName = firstName + " " + lastName;

        System.out.println(fullName);
    }
}

Output:

Output
Amit Patil

A Common Interview Trap#

Predict the output:

Java
public class ExpressionDemo {
    public static void main(String[] args) {
        System.out.println(10 + 20 + "Java");
        System.out.println("Java" + 10 + 20);
    }
}

Output:

Output
30Java
Java1020

Why?

Java evaluates operands from left to right.

First line:

Output
10 + 20 + "Java"

30 + "Java"

"30Java"

Second line:

Output
"Java" + 10 + 20

"Java10" + 20

"Java1020"

If we write:

Java
System.out.println("Java" + (10 + 20));

the parentheses force addition first.

Output:

Output
Java30

Micro-checkpoint#

Remember:

Once + starts performing String concatenation, subsequent + operations continue concatenating unless parentheses force another numeric expression to be evaluated first.

6. Subtraction Operator -#

Java
int balance = 1000;
int withdrawal = 300;

int remaining = balance - withdrawal;

System.out.println(remaining);

Output:

Output
700

7. Multiplication Operator *#

Suppose one product costs ₹250 and the customer buys four.

Java
int price = 250;
int quantity = 4;

int total = price * quantity;

System.out.println(total);

Output:

Output
1000

8. Division Operator /#

Division looks simple, but Java developers frequently make mistakes here.

Consider:

Java
int result = 10 / 2;
System.out.println(result);

Output:

Output
5

Now:

Java
int result = 5 / 2;
System.out.println(result);

What do you expect?

Mathematically:

Output
5 ÷ 2 = 2.5

But Java prints:

Output
2

Why?

Both operands are integers:

Java
5
2

Therefore Java performs integer division.

The fractional part is discarded.

It is not rounded.

Output
2.5 → 2

Getting a Decimal Result#

At least one operand must participate as a floating-point value.

Java
double result = 5.0 / 2;
System.out.println(result);

Output:

Output
2.5

This also works:

Java
double result = 5 / 2.0;

And:

Java
int a = 5;
int b = 2;

double result = (double) a / b;

A Very Common Mistake#

Java
double result = 5 / 2;

Some beginners expect:

Output
2.5

But the result is:

Output
2.0

Why?

First:

Output
5 / 2 → 2

Then Java converts that int result to double:

Output
2 → 2.0

The decimal information was already lost.

Correct:

Java
double result = 5.0 / 2;

or:

Java
double result = (double) 5 / 2;

9. Division by Zero#

This is where operand types matter dramatically.

Integer Division by Zero#

Java
int x = 10;
int y = 0;

System.out.println(x / y);

At runtime:

Output
ArithmeticException: / by zero

Floating-Point Division by Zero#

Java
double x = 10.0;
double y = 0.0;

System.out.println(x / y);

Output:

Output
Infinity

For:

Java
System.out.println(-10.0 / 0.0);

the result is:

Output
-Infinity

And:

Java
System.out.println(0.0 / 0.0);

produces:

Output
NaN

NaN means:

Not a Number.

Important production point#

Never assume that floating-point division by zero throws the same exception as integer division.


10. Remainder Operator %#

Suppose we divide:

Output
10 ÷ 3

We get:

Output
Quotient  = 3
Remainder = 1

The % operator returns the remainder.

Java
System.out.println(10 % 3);

Output:

Output
1

Even/Odd Example#

A number is even if division by 2 leaves remainder 0.

Java
int number = 14;

if (number % 2 == 0) {
    System.out.println("Even");
} else {
    System.out.println("Odd");
}

Cyclic Usage#

The remainder operator is useful when values must wrap around.

Example:

Java
int index = 7;
int size = 5;

int wrappedIndex = index % size;

System.out.println(wrappedIndex);

Output:

Output
2

This idea appears in:

  • circular buffers
  • pagination
  • rotation logic
  • hash-based calculations
  • alternating behavior

11. Negative Values and %#

Consider:

Java
System.out.println(-10 % 3);

Output:

Output
-1

In Java, integer remainder is consistent with:

Output
a == (a / b) * b + (a % b)

Because Java integer division truncates toward zero.

This means Java's % is technically a remainder operator, not always the mathematical modulo operation people expect for negative numbers.

For applications requiring mathematical floor-mod behavior, Java provides methods such as:

Java
Math.floorMod(...)

Example:

Java
System.out.println(-10 % 3);
System.out.println(Math.floorMod(-10, 3));

Output:

Output
-1
2

12. Numeric Promotion During Arithmetic#

A new concept has appeared.

Before continuing with operators, we need to understand what Java does when operand types differ.

Suppose:

Java
int x = 10;
double y = 2.5;

double result = x + y;

Java cannot simply perform int + double without determining a common numeric type.

Java performs numeric promotion.

For common arithmetic expressions, smaller integral types such as:

Output
byte
short
char

are generally promoted to:

Output
int

before arithmetic.


Important Example#

Java
byte a = 10;
byte b = 20;

// byte result = a + b;

That assignment does not compile.

Why?

a + b is evaluated as an int.

So conceptually:

Output
byte + byte
    ↓
int + int
    ↓
int

Correct:

Java
int result = a + b;

Or, if you are certain the value fits:

Java
byte result = (byte) (a + b);

But explicit narrowing can lose data.


13. Integer Overflow#

Consider:

Java
int value = Integer.MAX_VALUE;

System.out.println(value);
System.out.println(value + 1);

Output:

Output
2147483647
-2147483648

Java's ordinary integer arithmetic does not automatically throw an exception on overflow.

The value wraps according to the fixed-width two's-complement representation.

For code where overflow must be detected, APIs such as:

Java
Math.addExact()
Math.subtractExact()
Math.multiplyExact()

can be useful.

Example:

Java
int result = Math.addExact(Integer.MAX_VALUE, 1);

This throws:

Output
ArithmeticException

Production lesson#

For money, counters, IDs, quantities, financial calculations, and security-sensitive arithmetic, think explicitly about:

  • range
  • overflow
  • precision
  • validation

14. Unary Operators#

Until now, our arithmetic operators usually worked with two operands.

But sometimes we need to operate on only one value.

Java provides several unary operators.

Important ones include:

Output
+
-
++
--
!
~

15. Unary Plus +#

Java
int number = 10;
int result = +number;

result remains:

Output
10

Unary + usually has limited practical importance.


16. Unary Minus -#

Unary minus changes the sign.

Java
int number = 10;
int result = -number;

System.out.println(result);

Output:

Output
-10

If:

Java
int number = -10;
int result = -number;

then:

Output
10

17. Increment Operator ++#

Imagine a shopping cart.

Current quantity:

Java
int quantity = 1;

The customer clicks +.

We could write:

Java
quantity = quantity + 1;

Because increasing by one is extremely common, Java gives us:

Java
quantity++;

The ++ operator increases a variable by exactly 1.


18. Decrement Operator --#

Similarly:

Java
quantity--;

decreases the value by exactly 1.


19. Pre-Increment vs Post-Increment#

This distinction becomes important when the operator participates inside a larger expression.

Pre-Increment#

Java
++x

means:

Increment first, then produce the new value.

Post-Increment#

Java
x++

means:

Produce the current value first, then increment the variable.

20. Pre-Increment Example#

Java
public class PreIncrementDemo {
    public static void main(String[] args) {
        int x = 5;
        int y = ++x;

        System.out.println(x);
        System.out.println(y);
    }
}

Output:

Output
6
6

Execution:

Output
x = 5

++x
 ↓
x becomes 6
 ↓
expression produces 6

y = 6

21. Post-Increment Example#

Java
public class PostIncrementDemo {
    public static void main(String[] args) {
        int x = 5;
        int y = x++;

        System.out.println(x);
        System.out.println(y);
    }
}

Output:

Output
6
5

Execution:

Output
x = 5

x++
 ↓
expression first produces 5
 ↓
x becomes 6

y = 5
x = 6

22. Standalone Increment#

If we write:

Java
x++;

or:

Java
++x;

as standalone statements, both leave x increased by one.

Example:

Java
int x = 5;

x++;
System.out.println(x);

and:

Java
int x = 5;

++x;
System.out.println(x);

both print:

Output
6

The pre/post distinction matters primarily when the produced value participates in another expression.


23. Pre-Decrement#

Java
int x = 5;
int y = --x;

Result:

Output
x = 4
y = 4

24. Post-Decrement#

Java
int x = 5;
int y = x--;

Result:

Output
x = 4
y = 5

25. Dangerous Increment Expressions#

Consider:

Java
int x = 5;

int result = x++ + ++x;

Technically, Java defines the operand evaluation order, so this expression has deterministic behavior.

But that does not mean it is good code.

Execution:

Output
x = 5

x++
produces 5
x becomes 6

++x
x becomes 7
produces 7

result = 5 + 7
       = 12

final x = 7

This code is difficult to read.

Preferred production style#

Instead of compressing multiple mutations into one expression:

Java
int result = x++ + ++x;

write clear separate operations when practical.

Readability usually matters more than showing that you understand operator tricks.


26. Increment Cannot Be Applied Everywhere#

This is invalid:

Java
// 10++;

Why?

10 is a literal value.

There is no variable whose stored value can be updated.

Similarly, this is invalid:

Java
final int x = 10;

// x++;

A final variable cannot be reassigned.


27. Assignment Operator =#

We use:

Java
int age = 25;

The = operator assigns the value on the right to the variable on the left.

Think:

Output
Right side evaluated
        ↓
Result obtained
        ↓
Stored in left variable

Example:

Java
int a;
a = 10 + 20;

Java first evaluates:

Output
10 + 20 → 30

Then:

Output
a = 30

28. = Is Not Equality#

One of the most important beginner rules:

Output
=  → assignment
== → equality comparison

Example:

Java
int x = 10;

means:

Put 10 into x.

But:

Java
x == 10

asks:

Is x equal to 10?

It produces:

Output
true

or:

Output
false

29. Chained Assignment#

Assignment operators associate from right to left.

Example:

Java
int a;
int b;
int c;

a = b = c = 10;

Conceptually:

Output
a = (b = (c = 10))

After execution:

Output
a = 10
b = 10
c = 10

30. Compound Assignment Operators#

Suppose:

Java
int balance = 1000;
balance = balance + 500;

Java provides shorter syntax:

Java
balance += 500;

Important compound assignment operators include:

OperatorExample
+=x += 5
-=x -= 5
*=x *= 5
/=x /= 5
%=x %= 5
&=x &= y
| =x | = y
^=x ^= y
<<=x <<= 2
>>=x >>= 2
>>>=x >>>= 2

31. Compound Assignment Is More Than Shorter Syntax#

Now we reach an important Java-specific rule.

Consider:

Java
byte value = 10;

// value = value + 1;

This fails to compile because:

Output
byte + int
    ↓
int

and Java will not implicitly narrow that int to byte.

But:

Java
byte value = 10;

value += 1;

compiles.

Why?

Compound assignment includes an implicit conversion back to the left-hand variable type.

Conceptually:

Java
value += 1;

behaves roughly like:

Java
value = (byte) (value + 1);

This difference is a classic Java interview question.


Another Important Difference#

The Java Language Specification defines compound assignment so that the left-hand expression is evaluated only once.

That matters if the left side itself performs work.

Therefore:

Java
E1 op= E2

should not always be treated as a purely textual replacement for:

Java
E1 = E1 op E2

because the evaluation count of E1 may differ.


32. Relational Operators#

Suppose our application must determine whether a user is old enough.

We need questions such as:

Output
Is age greater than 18?
Is price less than 500?
Is score at least 40?

Java provides relational operators.

OperatorMeaning
<Less than
>Greater than
<=Less than or equal
>=Greater than or equal

These produce a boolean.


33. Relational Examples#

Java
int age = 25;

System.out.println(age > 18);
System.out.println(age < 18);
System.out.println(age >= 25);
System.out.println(age <= 20);

Output:

Output
true
false
true
false

34. Equality Operators#

Sometimes we need to know whether two values are equal or different.

Java provides:

Output
==
!=

== means equal according to the operator's type-specific rules.

!= means not equal.


35. Primitive Equality#

Java
int a = 10;
int b = 10;

System.out.println(a == b);

Output:

Output
true

For primitive numeric values, == compares their values after the necessary numeric conversions.


36. Boolean Equality#

Java
boolean a = true;
boolean b = false;

System.out.println(a == b);

Output:

Output
false

Normally, code such as:

Java
if (isActive) {
}

is clearer than:

Java
if (isActive == true) {
}

37. Reference Equality: A Critical Java Concept#

A new concept appears here.

Variables such as:

Java
String
Employee
Customer
ArrayList

usually hold references to objects.

For reference types, == answers:

Do these two references refer to the same object?

It does not generally mean:

Do these two objects contain logically equal data?

38. == with Strings#

Consider:

Java
String first = new String("Java");
String second = new String("Java");

System.out.println(first == second);

Output:

Output
false

Why?

Two separate objects were created.

Conceptually:

Output
first  ─────→ String object "Java"
second ─────→ different String object "Java"

Their content looks equal, but references differ.

For logical String content comparison:

Java
System.out.println(first.equals(second));

Output:

Output
true

39. Why String == Sometimes Appears to Work#

Consider:

Java
String first = "Java";
String second = "Java";

System.out.println(first == second);

This commonly prints:

Output
true

because String literals can refer to the same pooled String object.

That does not make == the correct general mechanism for comparing String content.

Production rule#

Use:

Java
first.equals(second)

when you mean String content equality, with appropriate null handling.

A null-safe pattern is:

Java
"Java".equals(value)

or:

Java
Objects.equals(first, second)

when Objects is appropriate for the surrounding code.


40. Wrapper Equality Trap#

Consider:

Java
Integer a = 127;
Integer b = 127;

System.out.println(a == b);

This may print:

Output
true

Now:

Java
Integer a = 128;
Integer b = 128;

System.out.println(a == b);

commonly prints:

Output
false

Why?

Wrapper objects may use cached instances for certain values.

The lesson is not to memorize a trick and use it in production.

The lesson is:

== on wrapper references tests reference identity unless unboxing/numeric promotion changes the expression.

Use logical equality where object equality is intended.


41. Autounboxing Can Introduce NullPointerException#

Consider:

Java
Integer count = null;

if (count == 0) {
    System.out.println("Zero");
}

To compare count with primitive 0, Java attempts to unbox count.

Conceptually:

Output
Integer null
    ↓
unbox to int
    ↓
impossible
    ↓
NullPointerException

This is an important production trap.


42. Floating-Point Equality and NaN#

Consider:

Java
double value = Double.NaN;

System.out.println(value == value);

Output:

Output
false

And:

Java
System.out.println(value != value);

Output:

Output
true

NaN has special floating-point comparison behavior.

Relational comparisons involving NaN such as:

Java
value < 10
value > 10
value <= 10
value >= 10

are false.

For domain-sensitive floating-point comparison, direct == may also be inappropriate because floating-point arithmetic can have representation error.

Example:

Java
double result = 0.1 + 0.2;

System.out.println(result);
System.out.println(result == 0.3);

Typical output:

Output
0.30000000000000004
false

For financial decimal arithmetic, developers often consider BigDecimal rather than binary floating-point types such as double.

That is a larger topic, but the operator lesson you must remember is:

Numeric-looking decimal values do not automatically behave like exact base-10 mathematics when stored as double.

43. Logical Operators#

Suppose a loan should be approved only when:

Output
age >= 18
AND
income >= 30000

One condition is not enough.

We need to combine boolean expressions.

Java provides logical operators.

Important boolean operators:

Output
&&
||
!
&
|
^

The most common are:

Output
&& → logical AND with short-circuiting
|| → logical OR with short-circuiting
!  → logical NOT

44. Logical AND &&#

Java
int age = 25;
double salary = 50000;

boolean eligible = age >= 18 && salary >= 30000;

System.out.println(eligible);

Both conditions must be true.

Truth table:

ABA && B
falsefalsefalse
falsetruefalse
truefalsefalse
truetruetrue

45. Logical OR ||#

Suppose a user may access an admin page if the user is either:

Output
ADMIN
OR
SUPER_ADMIN

Simplified example:

Java
boolean admin = false;
boolean superAdmin = true;

boolean allowed = admin || superAdmin;

System.out.println(allowed);

Output:

Output
true

Truth table:

ABA || B
falsefalsefalse
falsetruetrue
truefalsetrue
truetruetrue

46. Logical NOT !#

! reverses a boolean value.

Java
boolean active = true;

System.out.println(!active);

Output:

Output
false

Practical example:

Java
if (!isLoggedIn) {
    System.out.println("Please login.");
}

47. Exclusive OR ^ with Booleans#

^ can also operate on booleans.

It returns true when the boolean operands differ.

ABA ^ B
falsefalsefalse
falsetruetrue
truefalsetrue
truetruefalse

Example:

Java
boolean emailLogin = true;
boolean phoneLogin = false;

System.out.println(emailLogin ^ phoneLogin);

Output:

Output
true

This is less common than && and ||, but it is valid Java.


48. Short-Circuit Evaluation#

Now we reach one of the most important parts of the chapter.

Suppose we write:

Java
A && B

If Java evaluates A and discovers:

Output
A = false

does it need to evaluate B?

No.

For AND:

Output
false && anything

will always be:

Output
false

Therefore Java can skip B.

This behavior is called short-circuit evaluation.


49. Short-Circuit &&#

Java
boolean result = false && expensiveMethod();

Because the left operand is false, Java does not need the right operand to determine the final answer.

The right operand is skipped.


50. Short-Circuit ||#

For OR:

Output
true || anything

will always be true.

Therefore:

Java
boolean result = true || expensiveMethod();

does not need to execute expensiveMethod().


51. Short-Circuiting Can Prevent Errors#

Consider:

Java
String name = null;

if (name != null && name.length() > 3) {
    System.out.println("Long name");
}

Execution:

Output
name != null
     ↓
false
     ↓
&& already knows final result is false
     ↓
name.length() is NOT executed

Therefore no NullPointerException occurs.

If the conditions were reversed:

Java
if (name.length() > 3 && name != null) {
}

Java tries:

Java
name.length()

first.

Because name is null:

Output
NullPointerException

Decision rule#

When one condition protects the safety of another condition, put the safety condition first.


52. Preventing Division by Zero#

Java
int divisor = 0;

if (divisor != 0 && 100 / divisor > 10) {
    System.out.println("Condition matched");
}

The division is skipped when:

Output
divisor == 0

53. && vs & for Booleans#

This is frequently asked in interviews.

Both can operate on boolean values.

But:

Output
&& → short-circuit AND
&  → evaluates both operands

Example:

Java
public class AndDemo {
    static boolean check() {
        System.out.println("check() executed");
        return true;
    }

    public static void main(String[] args) {
        boolean result = false && check();

        System.out.println(result);
    }
}

Output:

Output
false

check() does not run.

Now:

Java
boolean result = false & check();

Output includes:

Output
check() executed
false

because & evaluates both boolean operands.


54. || vs |#

Similarly:

Output
|| → short-circuit OR
|  → evaluates both boolean operands

In everyday conditional logic, && and || are usually preferred when short-circuit semantics are intended.

& and | also have an important second role:

bitwise operations on integral values.

That brings us naturally to bitwise operators.


55. Why Bitwise Operators Exist#

Computers ultimately store integer values using bits.

For example, using four bits for illustration:

Output
5 = 0101
3 = 0011

Sometimes we need to manipulate individual bits.

This is common in:

  • flags
  • permissions
  • protocols
  • low-level systems
  • graphics
  • embedded programming
  • compact state representation
  • networking
  • masks

Java provides bitwise operators.


56. Bitwise Operators#

Important bitwise operators:

OperatorMeaning
&Bitwise AND
| Bitwise OR
^Bitwise XOR
~Bitwise complement

They operate on integral types after Java's numeric promotion rules.


57. Bitwise AND &#

Example:

Output
5 = 0101
3 = 0011

Perform AND bit by bit:

Output
  0101
& 0011
------
  0001

Result:

Output
1

Java:

Java
System.out.println(5 & 3);

Output:

Output
1

AND rule:

Output
1 & 1 → 1
otherwise → 0

58. Bitwise OR |#

Output
  0101
| 0011
------
  0111

0111 is:

Output
7

Java:

Java
System.out.println(5 | 3);

Output:

Output
7

59. Bitwise XOR ^#

XOR produces 1 when bits differ.

Output
  0101
^ 0011
------
  0110

Result:

Output
6
Java
System.out.println(5 ^ 3);

Output:

Output
6

60. Bitwise Complement ~#

~ flips every bit:

Output
0 → 1
1 → 0

For Java's signed two's-complement integers:

Java
System.out.println(~5);

Output:

Output
-6

A useful identity is:

Output
~x == -(x + 1)

for ordinary two's-complement integer values.


61. Bit Flags Example#

Suppose an application uses bit flags:

Java
int READ = 1;   // 0001
int WRITE = 2;  // 0010
int DELETE = 4; // 0100

Give a user READ and WRITE:

Java
int permissions = READ | WRITE;

Binary:

Output
0001
0010
----
0011

Check READ permission:

Java
boolean canRead = (permissions & READ) != 0;

This pattern appears frequently in systems where multiple boolean states are packed into bits.

For ordinary business applications, enums or other expressive abstractions may often be easier to maintain. Bit masks are valuable when their compact representation or protocol compatibility is actually needed.


62. Shift Operators#

We already know that numbers are represented by bits.

Sometimes we need to move those bits left or right.

Java provides:

Output
<<  left shift
>>  signed right shift
>>> unsigned right shift

63. Left Shift <<#

Example:

Java
int result = 5 << 1;

Simplified binary:

Output
5 = 00000101

shift left by 1:

00001010

Result:

Output
10
Java
System.out.println(5 << 1);

Output:

Output
10

For values where no relevant overflow occurs:

Output
x << n

often corresponds to multiplication by:

Output
2^n

But do not blindly use this as a replacement for normal multiplication.

Overflow and readability matter.


64. Signed Right Shift >>#

Example:

Java
System.out.println(8 >> 1);

Binary movement corresponds to:

Output
8 → 4

Output:

Output
4

For positive numbers, right shift often resembles division by powers of two.

For negative values, >> preserves the sign by filling high-order bits with the sign bit.

This is called sign extension.


65. Unsigned Right Shift >>>#

>>> shifts bits right but fills the high-order positions with zeros.

Example:

Java
int value = -8;

System.out.println(value >> 1);
System.out.println(value >>> 1);

The two results differ dramatically because:

Output
>>  preserves sign
>>> inserts zero bits

For int:

Output
-8 >> 1   → -4
-8 >>> 1  → 2147483644

66. Why >>> Is Called Unsigned Right Shift#

Java's commonly used integral types such as int and long are signed.

But >>> lets us perform a right shift without propagating the sign bit.

It does not transform Java's int into a completely different unsigned integer type.

It is simply a zero-fill right shift operation.


67. Shift Distance Rules#

An advanced but important rule:

For int shifts, Java uses only the low five bits of the shift distance.

Effectively the shift distance is constrained modulo 32.

For long, Java uses the low six bits.

Effectively modulo 64.

Therefore:

Java
System.out.println(1 << 32);

prints:

Output
1

because for int:

Output
32 → effective shift distance 0

Similarly:

Java
System.out.println(1 << 33);

behaves like:

Java
1 << 1

and prints:

Output
2

This is an excellent interview trap.


68. Smaller Integral Types and Shifts#

Consider:

Java
byte value = 1;

int result = value << 2;

The shift expression produces an int because smaller integral operands are promoted.

This is another reason bitwise and shift code must be written with careful awareness of type conversion.


69. Ternary Operator ?:#

Suppose we want:

Output
If age >= 18
    status = "Adult"
else
    status = "Minor"

Using if/else:

Java
String status;

if (age >= 18) {
    status = "Adult";
} else {
    status = "Minor";
}

When the goal is simply to choose between two values, Java provides the conditional operator:

Java
condition ? valueIfTrue : valueIfFalse

Example:

Java
String status = age >= 18 ? "Adult" : "Minor";

70. How Ternary Works#

Java
int age = 20;

String status = age >= 18 ? "Adult" : "Minor";

Flow:

Output
age >= 18
    ↓
 true
    ↓
choose "Adult"

Only the chosen operand expression is evaluated.


71. Ternary Is an Expression#

This is important.

if/else is a statement structure.

The conditional operator produces a value.

Therefore it can participate in expressions.

Example:

Java
int max = a > b ? a : b;

72. Do Not Abuse Nested Ternary Expressions#

Possible:

Java
String grade = score >= 80 ? "A" : score >= 60 ? "B" : score >= 40 ? "C" : "Fail";

Technically valid.

But readability may become poor.

A clearer version may be:

Java
String grade;

if (score >= 80) {
    grade = "A";
} else if (score >= 60) {
    grade = "B";
} else if (score >= 40) {
    grade = "C";
} else {
    grade = "Fail";
}

Decision rule#

Use ternary when:

  • the condition is simple
  • you are selecting between values
  • readability remains high

Prefer if/else when:

  • multiple statements are required
  • branching logic is complex
  • nested ternaries make intent difficult to read

73. instanceof Operator#

Suppose we have a variable whose declared type is broad:

Java
Object value;

At runtime it could refer to:

Output
String
Integer
Employee
Customer
...

Sometimes we need to ask:

Does this object belong to a particular type?

Java provides:

Java
instanceof

74. Basic instanceof#

Java
Object value = "Java";

System.out.println(value instanceof String);

Output:

Output
true

75. instanceof and Inheritance#

Consider:

Java
class Animal {
}

class Dog extends Animal {
}

Now:

Java
Dog dog = new Dog();

System.out.println(dog instanceof Dog);
System.out.println(dog instanceof Animal);

Output:

Output
true
true

A Dog object is also an instance compatible with its superclass Animal.


76. instanceof with null#

A very useful rule:

Java
Object value = null;

System.out.println(value instanceof String);

Output:

Output
false

It does not throw NullPointerException.

Therefore classic code such as:

Java
if (value instanceof String) {
    String text = (String) value;
}

is safe from a null cast path because a null reference does not satisfy the instanceof test.


77. instanceof and Casting#

Classic Java code often uses:

Java
Object value = "Java";

if (value instanceof String) {
    String text = (String) value;
    System.out.println(text.length());
}

The instanceof check verifies that the runtime object is compatible with the requested type before the cast.

Without a safe relationship, an incorrect cast can produce:

Output
ClassCastException

78. Version Note: Pattern Matching for instanceof#

Modern Java versions support pattern matching syntax such as:

Java
if (value instanceof String text) {
    System.out.println(text.length());
}

This removes the separate explicit cast.

However, this syntax is from later Java versions and should not be presented as Java 8 syntax.

Classic syntax remains essential when studying older Java versions:

Java
if (value instanceof String) {
    String text = (String) value;
}

79. Generic Type Limitation with instanceof#

Because of Java's generic type erasure rules, code such as this is not allowed:

Java
// if (value instanceof List<String>) {
// }

But a reifiable form such as:

Java
if (value instanceof java.util.List<?>) {
}

can be used.

You do not need a complete generics lesson here.

Remember only the chapter-relevant rule:

Runtime instanceof checks cannot generally test parameterized generic type arguments such as List<String>.

80. Operator Precedence#

Now imagine this expression:

Java
int result = 10 + 5 * 2;

Should Java calculate:

Output
10 + 5 = 15
15 * 2 = 30

or:

Output
5 * 2 = 10
10 + 10 = 20

Java needs rules for deciding which operator binds first.

Those rules are called operator precedence.

Because multiplication has higher precedence than addition:

Output
10 + 5 * 2
     ↓
10 + 10
     ↓
20

81. Parentheses Override Normal Grouping#

Java
int result = (10 + 5) * 2;

Now:

Output
10 + 5
   ↓
15

15 * 2
   ↓
30

Parentheses are not only for changing behavior.

They can also improve readability.

In production code:

Clear intent is often better than relying on readers to remember a large precedence table.

82. Practical Precedence Order#

From higher precedence toward lower precedence, an important simplified Java order is:

LevelOperators
Highpostfix expr++, expr--
unary ++, --, +, -, !, ~
multiplicative *, /, %
additive +, -
shift <<, >>, >>>
relational <, >, <=, >=, instanceof
equality ==, !=
bitwise AND &
bitwise XOR ^
bitwise OR |
logical AND &&
logical OR | |
ternary ?:
Lowassignments =, +=, -=, etc.

Parentheses and primary expressions conceptually bind more tightly than these operator groups.


83. Precedence Example#

Predict:

Java
boolean result = 10 > 5 && 3 < 1 || true;

Grouping:

Output
(10 > 5) && (3 < 1) || true

Then:

Output
true && false || true

&& has higher precedence than ||:

Output
false || true

Final result:

Output
true

84. Operator Associativity#

Precedence answers:

Which operator group binds first?

Associativity answers:

When operators of the same precedence appear together, how are they grouped?

Example:

Java
int result = 20 - 5 - 3;

Subtraction is left-associative:

Output
(20 - 5) - 3

Result:

Output
12

Not:

Output
20 - (5 - 3)

which would be:

Output
18

85. Right Associativity#

Assignment operators associate right-to-left.

Java
a = b = c = 10;

Grouping:

Output
a = (b = (c = 10))

The conditional operator also groups right-associatively.


86. Associativity Is NOT Evaluation Order#

This distinction is extremely important.

Students often believe:

If an operator is right-associative, Java must evaluate operands from right to left.

That is incorrect.

Associativity determines grouping.

Java has separate rules governing operand evaluation, and Java generally evaluates operand expressions from left to right.

Example:

Java
int result = first() + second();

first() is evaluated before second().

This predictable evaluation order distinguishes Java from languages or contexts where operand evaluation order may be less strictly defined.


87. Expression Evaluation#

Let us examine an expression slowly:

Java
int result = 10 + 20 * 3;

Java conceptually determines grouping according to precedence:

Output
10 + (20 * 3)

Then computes:

Output
20 * 3 = 60

then:

Output
10 + 60 = 70

and finally:

Output
result = 70

88. Method Calls Inside Expressions#

Java
int result = getA() + getB();

Java evaluates:

Output
getA()
then
getB()
then
+

If the methods have side effects, their order can matter.

Example:

Java
public class EvaluationOrderDemo {
    static int first() {
        System.out.println("first");
        return 10;
    }

    static int second() {
        System.out.println("second");
        return 20;
    }

    public static void main(String[] args) {
        int result = first() + second();
        System.out.println(result);
    }
}

Output:

Output
first
second
30

89. Side Effects Inside Expressions#

A side effect means an expression does more than simply calculate a value.

Examples include:

  • changing a variable
  • writing output
  • modifying an object
  • performing I/O

Increment operators create side effects.

Example:

Java
int x = 5;
int result = x++ + 10;

The expression:

  • produces a value
  • changes x

This is valid, but excessive side effects inside complex expressions make code harder to reason about.


90. Constant Expressions and Division by Zero#

There is an important distinction.

This:

Java
int zero = 0;
int result = 10 / zero;

can compile and then fail at runtime with:

Output
ArithmeticException

But a compile-time constant integer expression such as:

Java
// int result = 10 / 0;

is rejected during compilation.

This is because the compiler can already determine that the constant integer expression contains division by zero.


91. Arithmetic Promotion Summary#

For ordinary binary numeric operators, a useful mental model is:

Output
If double involved → double
else if float involved → float
else if long involved → long
else → int

Therefore:

Output
byte + byte   → int
short + short → int
char + char   → int
int + long    → long
long + float  → float
float + double → double

This simplified model covers the common binary numeric-promotion behavior you will repeatedly encounter.


92. char Is Numeric in Arithmetic Expressions#

Consider:

Java
char ch = 'A';

System.out.println(ch + 1);

'A' has numeric Unicode value:

Output
65

So:

Output
65 + 1 → 66

Output:

Output
66

If you want a character:

Java
char next = (char) (ch + 1);

System.out.println(next);

Output:

Output
B

93. Commonly Confused Concepts#

= vs ==#

===
AssignmentEquality comparison
Stores valueProduces boolean
x = 10x == 10

== vs .equals()#

==.equals()
OperatorMethod
Primitive value comparison where applicableObject-defined logical equality
Reference identity for referencesUsually logical/content equality when properly implemented
Cannot be overriddenMethod behavior can be overridden

Decision rule:

Output
Comparing primitives?
→ usually ==

Need object identity?
→ ==

Need logical object equality?
→ equals()

&& vs &#

&&&
Boolean onlyBoolean or integral
Short-circuitsEvaluates both boolean operands
Common conditional operatorBoolean non-short-circuit or bitwise AND

|| vs |#

|||
Boolean onlyBoolean or integral
Short-circuitsEvaluates both boolean operands
Common logical ORBoolean non-short-circuit or bitwise OR

>> vs >>>#

>>>>>
Signed right shiftZero-fill right shift
Preserves sign bitInserts zero bits
Negative values usually remain negativeNegative values may become large positive values

Pre-Increment vs Post-Increment#

++xx++
Increment firstProduce old value first
Expression gives new valueExpression gives old value
Standalone effect sameStandalone effect same

94. Operator Decision Rules#

Output
Need arithmetic?
→ + - * / %

Need to increase/decrease exactly one?
→ ++ or --

Need to assign?
→ =

Need update-and-assign?
→ += -= *= /= %= etc.

Need numeric ordering?
→ < > <= >=

Need equality?
→ == or !=
→ for logical object equality consider equals()

Need both boolean conditions?
→ &&

Need either boolean condition?
→ ||

Need reverse boolean?
→ !

Need bit-level AND/OR/XOR?
→ & | ^

Need flip integral bits?
→ ~

Need move bits?
→ << >> >>>

Need choose one of two values?
→ ?:

Need runtime type compatibility check?
→ instanceof

95. Common Mistakes#

Mistake 1 — Expecting Decimal Result from Integer Division#

Mistake:

Java
double average = 5 / 2;

Why Developers Make It:

The variable receiving the result is double.

Why It Is Wrong/Risky:

5 / 2 is completed using integer arithmetic before assignment.

Possible Consequence:

Incorrect calculations.

Preferred Approach:

Java
double average = 5.0 / 2;

Debugging Clue:

Decimal portions unexpectedly disappear.

Interview Connection:

Frequently appears in output questions.


Mistake 2 — Using == for String Content#

Risky:

Java
if (name == "Java") {
}

Problem:

Reference identity may be tested instead of logical String content.

Preferred:

Java
if ("Java".equals(name)) {
}

or another appropriate null-safe equality strategy.


Mistake 3 — Putting Unsafe Condition First#

Risky:

Java
if (name.length() > 3 && name != null) {
}

Consequence:

Potential NullPointerException.

Preferred:

Java
if (name != null && name.length() > 3) {
}

Mistake 4 — Using & When && Was Intended#

Java
if (object != null & object.isValid()) {
}

Both sides are evaluated.

If object is null:

Output
NullPointerException

Preferred:

Java
if (object != null && object.isValid()) {
}

Mistake 5 — Assuming byte + byte Returns byte#

Java
byte a = 10;
byte b = 20;

// byte c = a + b;

Arithmetic promotes the operands.

Use:

Java
int c = a + b;

Mistake 6 — Overusing Increment Inside Complex Expressions#

Risky readability:

Java
int result = x++ + ++x * x--;

Even if you can calculate it, teammates should not need to solve a puzzle to understand production code.

Prefer explicit steps.


Mistake 7 — Assuming Integer Overflow Throws Automatically#

Java
int value = Integer.MAX_VALUE;
value++;

No ordinary overflow exception is automatically thrown.

Validate ranges or use exact arithmetic helpers when required.


Mistake 8 — Comparing Floating-Point Results with Exact ==#

Risky for calculated decimal values:

Java
double result = 0.1 + 0.2;

if (result == 0.3) {
}

Floating-point representation can make exact comparison unsuitable for the requirement.


Mistake 9 — Treating % as Mathematical Modulo for Negative Inputs#

Java
System.out.println(-10 % 3);

produces:

Output
-1

If your algorithm requires non-negative floor-mod semantics, examine Math.floorMod().


Mistake 10 — Believing >>> Creates an Unsigned Type#

It does not.

It performs zero-fill right shifting.


Mistake 11 — Relying on Precedence in Hard-to-Read Expressions#

Valid:

Java
if (a > b && c < d || enabled) {
}

Clearer when the intended grouping matters:

Java
if ((a > b && c < d) || enabled) {
}

Mistake 12 — Confusing Associativity with Evaluation Order#

Associativity decides grouping.

It does not mean method calls are necessarily evaluated according to the associativity direction.

Java operand evaluation follows its own defined order.


96. Production Perspective#

Operators are basic language features, but operator mistakes cause real defects.

Important production concerns include:

Correctness#

Be careful with:

  • integer division
  • overflow
  • narrowing conversions
  • floating-point precision
  • negative remainder behavior

Null Safety#

Short-circuit conditions often protect operations:

Java
user != null && user.isActive()

Readability#

Prefer:

Java
boolean eligible = age >= 18 && hasPermission;

over unnecessarily clever bitwise or nested ternary constructions.

Maintainability#

Parentheses can make intent clearer even when precedence already produces the same result.

Security#

Overflow or incorrect numeric validation can become security issues in sensitive code.

Performance#

Short-circuit operators can avoid unnecessary work:

Java
cached || expensiveLookup()

But correctness should come before micro-optimization.

Financial Applications#

Do not treat ordinary double arithmetic as exact decimal currency arithmetic without understanding its implications.

Testing#

Test boundaries such as:

Output
0
1
-1
Integer.MAX_VALUE
Integer.MIN_VALUE
null
division by zero
negative operands
equal operands

97. Complete Chapter Revision#

One-Line Definitions#

Operator: Symbol that performs an operation.

Operand: Value on which an operator acts.

Expression: Combination evaluated to produce a value.

Arithmetic operator: Performs arithmetic such as +, -, *, /, %.

Unary operator: Operates on one operand.

Increment: ++, increases variable by one.

Decrement: --, decreases variable by one.

Assignment: =, stores a right-side value into a left-side variable.

Relational operator: Compares ordering and produces boolean.

Equality operator: == or !=.

Short-circuit: Skips unnecessary evaluation of the right operand.

Bitwise operator: Manipulates integral values at bit level.

Shift operator: Moves bit patterns left or right.

Ternary operator: condition ? a : b.

instanceof: Checks runtime type compatibility.

Precedence: Determines operator grouping priority.

Associativity: Determines grouping among operators of the same precedence.


98. If You Remember Only 10 Things#

  1. = assigns; == compares.
  2. 5 / 2 produces 2, not 2.5.
  3. byte + byte normally produces int.
  4. x++ produces the old value before increment; ++x produces the new value.
  5. && and || short-circuit.
  6. & and | do not short-circuit when used with booleans.
  7. == compares reference identity for ordinary reference comparisons; use logical equality methods when content equality is intended.
  8. >> sign-extends; >>> zero-fills.
  9. Precedence and associativity are not the same as operand evaluation order.
  10. Prefer readable expressions over clever operator puzzles.

99. Final Knowledge Map#

Output
Java Operators and Expressions
│
├── Foundation
│   ├── Operator
│   ├── Operand
│   ├── Expression
│   └── Unary / Binary / Ternary
│
├── Arithmetic
│   ├── +
│   ├── -
│   ├── *
│   ├── /
│   ├── %
│   ├── Integer Division
│   ├── Numeric Promotion
│   ├── Overflow
│   └── Floating-Point Behavior
│
├── Unary
│   ├── Unary +
│   ├── Unary -
│   ├── ++
│   ├── --
│   ├── Pre-Increment
│   ├── Post-Increment
│   ├── Pre-Decrement
│   └── Post-Decrement
│
├── Assignment
│   ├── =
│   ├── +=
│   ├── -=
│   ├── *=
│   ├── /=
│   ├── %=
│   └── Bitwise/Shift Compound Assignments
│
├── Comparison
│   ├── <
│   ├── >
│   ├── <=
│   ├── >=
│   ├── ==
│   ├── !=
│   ├── Primitive Equality
│   └── Reference Equality
│
├── Logical
│   ├── &&
│   ├── ||
│   ├── !
│   ├── Boolean &
│   ├── Boolean |
│   ├── Boolean ^
│   └── Short-Circuit Evaluation
│
├── Bitwise
│   ├── &
│   ├── |
│   ├── ^
│   └── ~
│
├── Shifts
│   ├── <<
│   ├── >>
│   ├── >>>
│   └── Shift-Distance Masking
│
├── Conditional
│   └── ?:
│
├── Type Checking
│   └── instanceof
│
└── Expression Rules
    ├── Precedence
    ├── Associativity
    ├── Left-to-Right Operand Evaluation
    ├── Numeric Promotion
    ├── Side Effects
    └── Short-Circuiting

Practice lab

Prove what you just learned