Operators: arithmetic, relational, logical, bitwise

Operators are the verbs of a program: add, compare, combine, flip bits. Most look familiar from maths, but a few hide surprises: x++ vs ++x, % with negative numbers, && skipping its right side, and | working on individual bits. This lesson shows the order Java evaluates things in, step by step.

Module 2 · Language Basics⏱ 19 minBeginnerNo install needed8 practice problems
1 The story

The canteen offer

The canteen runs an offer: “If your bill is over ₹70 and you're a member, get a free chai.” Riya writes the bill logic: price × quantity, plus a packing charge, plus 10% tax, then the offer check. Her first version gives free chai to everybody. Arjun Sir looks at one line and smiles.

20 + 3 * 5 Left to right would give 115. Java gives 35. Why? + 20 * 3 5 ① = 15 ② = 35 myphatshala.in
Riya

Sir, I wrote isMember || total > 70 && isStudent and everyone who's a member gets free chai, even with a ₹20 bill!

Arjun Sir

Because && binds tighter than ||, just like * binds tighter than +. Java read it as isMember || (total > 70 && isStudent). Operators have a ranking called precedence.

Riya

So I should add brackets to say exactly what I mean.

Arjun Sir

Always, when you mix operators. Let's go through every operator family, and watch the order Java follows behind the screen.

2 Definition

What is an operator?

Formal definition (write this in exams)

An operator is a symbol that performs an operation on one, two or three operands and produces a result. Java's operators are grouped as arithmetic, unary (including increment/decrement), assignment, relational, logical, bitwise and shift, the ternary conditional operator, and instanceof. When an expression contains several operators, precedence decides which is applied first and associativity decides the order among operators of equal precedence.

In simple words

Operators are action symbols: + adds, > compares, && joins conditions. Like BODMAS in school maths, Java has rules about which action happens first. Brackets always win.

Words you'll meet in this lesson

OperandA value an operator works on. In a + b, a and b are operands.
Unary / binary / ternaryOperators with one (-x), two (a + b) or three (c ? a : b) operands.
PrecedenceWhich operator is applied first. * before +; && before ||.
AssociativityOrder among equal-precedence operators. Most go left to right; assignment goes right to left.
Short-circuit&& and || skip the right side when the left side already decides the answer.
Side effectA change an expression makes, like x++ changing x while also producing a value.

All operator families

FamilyOperatorsExample → result
Arithmetic+ - * / %17 / 5 → 3 · 17 % 5 → 2
Unary+ - ++ -- !-x · count++ · !isPaid
Assignment= += -= *= /= %= …total += 10 means total = total + 10
Relational== != < > <= >=marks >= 40 → true/false
Logical&& || !age >= 18 && hasId
Bitwise& | ^ ~5 & 3 → 1 · 5 | 3 → 7 · 5 ^ 3 → 6
Shift<< >> >>>1 << 10 → 1024
Ternary? :marks >= 40 ? "Pass" : "Fail"
Type checkinstanceofobj instanceof String (Module 7)

Exam tip: the precedence order to remember, highest first: postfix (x++) → unary (++x, !, −) → * / % → + − → shifts → relational (< >) → equality (== !=) → & → ^ → | → && → || → ?: → assignment. When in doubt, use brackets: they make the code clearer for humans too.

3 Types and ways to use it

The tricky operators, up close

x++ vs ++x

Postfix x++: use the old value, then add 1. Prefix ++x: add 1 first, then use the new value. Alone on a line, both just add 1.

Order matters

/ and %

Integer / drops the fraction; % gives the remainder. 17 samosas for 5 friends: 17 / 5 = 3 each, 17 % 5 = 2 left. % keeps the sign of the left side: -7 % 3 = −1.

Sign trap

&& and || short-circuit

a && b: if a is false, b is never evaluated. a || b: if a is true, b is skipped. That's why s != null && s.length() > 0 is safe.

Skips work

Bitwise & | ^ ~

Work on each bit separately. Used for flags and permissions: READ | WRITE combines; perms & WRITE tests. On booleans, & and | evaluate both sides (no short-circuit).

Bit-level

Shift operators

OperatorMeaningExample
<<Shift bits left, fill with 0 (× 2 per step)3 << 2 → 12
>>Shift right, keep the sign bit (÷ 2, rounding down)-7 >> 1 → −4
>>>Shift right, fill with 0 (unsigned shift)-7 >>> 28 → 15

String +: when either operand of + is a String, it means “join”. Evaluation is left to right, so 1 + 2 + "3" + 4 + 5 gives "3345": 1 + 2 = 3 first, then everything after the string is joined.

4 Step by step

How Java evaluates an expression

Take total = price * qty + 10 > 70 && member. Java follows the same steps for any expression.

  1. Group by precedence

    javac adds invisible brackets: total = (((price * qty) + 10) > 70) && member.

    This happens while parsing. The compiler builds a tree where higher-precedence operators sit lower, closer to the values.
  2. Evaluate operands left to right

    Java always evaluates the left operand of a binary operator before the right one.

    Unlike C, this order is guaranteed by the Java specification, so a++ + a always gives the same result on every JVM.
  3. Apply each operator

    price * qty → 60, + 10 → 70, > 70 → false.

    In bytecode this is a sequence on the operand stack: iload, iload, imul, bipush 10, iadd, then a comparison and a jump.
  4. Short-circuit if possible

    The left side of && is false, so member is never read.

    javac compiles && into a conditional jump: if the left side is false, jump straight past the right side.
  5. Assign the result

    The final value goes into total. Assignment has the lowest precedence and works right to left: a = b = 5 sets b first, then a.

    An assignment is itself an expression whose value is the assigned value. That's why if (x = 5) is a type error in Java: the result is an int, not a boolean.
5 See it happen

Six operator surprises: both views

Left: the code and what prints. Right: the order of evaluation and the bits.

Operators in action 6 steps
What you see int r = 20 + 3 * 5; int a = 5;int b = a++ + ++a; 17 / 5 and 17 % 5-7 % 3 String s = null;s != null && s.length() > 3 READ = 1, WRITE = 2, EXEC = 4perms = READ | WRITE; String r = marks >= 40 ? "Pass" : "Fail"; 35 b = 12, a = 7 3 2 -1 false (no crash!) perms = 3; perms & WRITE = 2 → allowed Pass (when marks = 87) * is done before +. 5 + 7, and a was increased twice. Remainder keeps the sign of the left side. The right side never ran. Several yes/no flags in one int. A compact if-else that produces a value. myphatshala.in
Behind the screen + 20 * 3 5 bipush 20 · iconst_3 · iconst_5 · imul · iadd (javac actually folds constants to 35 at compile time) a++value used: 5then a becomes 6 ++aa becomes 7 firstvalue used: 7 b = 5 + 7 = 12, a = 7 iload a · iinc a,1 · iinc a,1 · iload a · iadd Left operand is always evaluated before the right. 555 17 / 5 = 3 groups17 % 5 = 2 left Java's rule: a = (a / b) * b + (a % b) -7 / 3 = -2 (towards zero) -7 % 3 = -7 - (-6) = -1 For an always-positive result: Math.floorMod(-7, 3) = 2 s != nullfalse && s.length() > 3skipped result false Bytecode: ifnull → jump past the right side. With single &, both sides run → NullPointerException. READ = 001 WRITE = 010 EXEC = 100 READ | WRITE = 011 (3) perms & WRITE = 011 & 010 = 010 ≠ 0 ✓ perms & EXEC = 011 & 100 = 000 = 0 ✗ Each bit is one yes/no flag. One int can hold 32 flags. marks >= 40 ? truefalse "Pass" "Fail" Only the chosen side is evaluated. Same bytecode shape as an if-else. myphatshala.in
6 Real-world use

Operators in real systems

Operators look like school maths, but in production code they do some clever jobs.

Watch it with an example: checkout rules at an online store

Cart total Rs 850, the customer is a member. Watch each operator do its job, in the order Java evaluates them.

Operators deciding a discount 6 steps
Animated example int total = 850; boolean member = true; int gst = total * 18 / 100; boolean big = total >= 500; if (big && member) discount = 100; int fee = (total >= 999) ? 0 : 40; pay = total + gst - discount + fee; total 850 gst 153 big true discount 100 fee 40 pay 943 Start values * and / left to right: 850*18 = 15300, /100 = 153 Relational >= gives a boolean: true &&: both must be true true && true → true Ternary ? : picks one 850 >= 999 false → 40 Arithmetic, left to right 850+153−100+40 = 943 Pay Rs 943 myphatshala.in
id % 4

1. Spreading data across servers

Systems often decide which server or partition stores a record with the remainder operator, like userId % 4. Kafka and many databases use the same idea with hash values.

userId 1027→1027 % 4 = 3→Server 3
R ✓W ✓X ✗perms = 011

2. Permissions and feature flags

File permissions (like Linux's read/write/execute) and some feature-flag systems pack many yes/no options into one number, combined with | and tested with &.

READ | WRITE→perms & WRITE != 0→Allowed
user != null &&

3. Safe and fast checks with short-circuiting

Code puts the cheap or null-safe check first: user != null && user.isActive(), or cache.has(key) || loadFromDatabase(key), so the expensive or risky part runs only when needed.

Cheap check→&& / || skip the rest→Fewer DB calls, no NPE
hash >>> 16& (n - 1)

4. Inside Java's own HashMap

HashMap mixes bits of a key's hash with ^ and >>>, then picks a bucket with & (n - 1), a fast replacement for % when n is a power of two (Lesson 11.6).

key.hashCode()→h ^ (h >>> 16), & (n−1)→Bucket index
Pay ₹450Free delivery ✓

5. Business rules in checkout

Offers such as “free delivery if the cart is over ₹399 or the user is a member, and the address is serviceable” are logical expressions. Getting the brackets right is the difference between a promotion and a loss.

(cart > 399 || member)→&& serviceable→Free delivery

Examples are simplified to show where operators fit. Real implementations vary.

7 Run the code

Riya's canteen bill

public class Main {
    public static void main(String[] args) {
        int price = 20, qty = 3;
        int total = price * qty + 10;          // * before +
        total += total / 10;                   // add 10% tax
        int a = 5;
        int b = a++ + ++a;                     // 5 + 7
        boolean member = total > 70 && a % 2 == 1;
        String msg = member ? "Free chai!" : "No offer";
        System.out.println(total + " " + a + " " + b + " " + msg);
    }
}
77 7 12 Free chai!
  • price * qty + 10Multiplication first: 60 + 10 = 70.
  • total += total / 10;Compound assignment: 70 + 7 = 77 (integer division).
  • a++ + ++aUses 5, then a becomes 6; then a becomes 7 and 7 is used. b = 12.
  • total > 70 && a % 2 == 1Relational and equality operators bind tighter than &&: true && true.
  • member ? … : …The ternary operator picks one of two values.
8 Line by line

Evaluate it like the JVM

Each step shows how the expression on that line is broken down and in which order.

Worked examples: real problems, solved and traced in memory

Operators turn values into answers: arithmetic, comparison, logical, compound assignment and increment. Each program below answers a real business question with nothing but operators. Watch the variables change on the stack after each expression.

Example 1Retail · checkout

Build a bill with compound assignment

Problem statement

A checkout adds three items to a total, applies a 10% discount, adds Rs 40 delivery, and splits the bill across 3 friends. Use +=, *=, / and %.

Input
items 450, 299, 180; 10% off; delivery 40; 3 people
Expected output
Bill: Rs 876
Each pays Rs 292, leftover Rs 0

Approach

  1. total += price adds to the running total.
  2. total *= 0.9 applies the discount.
  3. Whole-rupee share with /, leftover with %.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 2Calendar · leap years

Is it a leap year? Logical operators

Problem statement

A billing system must know whether February has 29 days. A year is a leap year if it's divisible by 4 and not by 100, or if it's divisible by 400. Check 2024, 1900 and 2000.

Input
2024, 1900, 2000
Expected output
2024: true
1900: false
2000: true

Approach

  1. year % 4 == 0 tests divisibility.
  2. Combine with && (and), || (or), != (not equal).
  3. Store each result in a boolean.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

Example 3Restaurant · tokens

Token numbers with ++: before or after?

Problem statement

A restaurant hands out tokens. next++ gives the current number and then increases it; ++next increases first. Hand out two tokens with next++, then peek at the following number with ++next.

Input
tokens start at 101
Expected output
Asha: 101, Ravi: 102
next is now 104, peek was 104

Approach

  1. int t = next++;: t gets 101, next becomes 102.
  2. Repeat for the second customer.
  3. ++next increases first, then gives the new value.

Solution: run it live

What happens in memory, step by step

Recorded from the real JVM: press Next to execute one line at a time. Watch method calls push and pop frames on the stack, and objects (numbered #1, #2 …) appear on the heap.

9 Quiz and revision

Check yourself

Quick revision

Lesson 2.5 in one screen

  • Arithmetic + - * / %; int / int drops decimals; % keeps the left sign.
  • x++ uses then adds; ++x adds then uses.
  • Relational/equality give booleans. = assigns, == compares.
  • && / || short-circuit; & / | always evaluate both sides.
  • Bitwise & | ^ ~ and shifts << >> >>> work bit by bit; used for flags and hashing.
  • Ternary cond ? a : b evaluates only the chosen side.
  • Precedence: postfix → unary → * / % → + − → shifts → relational → equality → & ^ | → && → || → ?: → =. Use brackets.

Interview and viva questions

What is the difference between & and && in Java?

Both can be used on booleans. && is short-circuit: it skips the right side if the left is false. & always evaluates both sides. & is also the bitwise AND for integers.

What is the output of i = i++ when i is 10?

i stays 10. i++ produces the old value 10 and increments i to 11, but then the assignment stores the produced value 10 back into i, overwriting the 11.

What is the difference between >> and >>>?

>> is an arithmetic shift that copies the sign bit, so negative numbers stay negative. >>> is a logical shift that always fills with zeros, so the result is non-negative.

Does Java support operator overloading?

Not for user-defined classes. The only built-in overload is + for String concatenation.

Why can't we write if (x = 5) in Java?

Because an assignment expression has the type of the variable (int here), and an if condition must be boolean. This rule catches a classic C bug at compile time. It only compiles if x itself is a boolean.

Practice problems

Arithmetic, comparison, logical, compound and increment operators. Predict each result first. The last three are business tasks.

P1Easy

Remainder

Print 17 % 5 and 20 % 5.

Input
(none)
Expected output
2 0
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        System.out.println(17 % 5 + " " + 20 % 5);
    }
}
2 0

How it works: % gives the remainder after division; 0 means divisible.

P2Easy

Even or odd as boolean

Print whether 42 and 17 are even.

Input
42, 17
Expected output
true false
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        System.out.println((42 % 2 == 0) + " " + (17 % 2 == 0));
    }
}
true false

How it works: comparison operators produce booleans.

P3Easy

Compound assignment

Start x at 10; do x += 5, x *= 3, x -= 7, x /= 2 and print x.

Input
10
Expected output
19
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int x = 10;
        x += 5;
        x *= 3;
        x -= 7;
        x /= 2;
        System.out.println(x);
    }
}
19

How it works: 10 → 15 → 45 → 38 → 19.

P4Medium

Ternary operator

Print "PASS" if marks (58) are 40 or more, else "FAIL", using ? :.

Input
58
Expected output
PASS
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int marks = 58;
        System.out.println(marks >= 40 ? "PASS" : "FAIL");
    }
}
PASS

How it works: condition ? valueIfTrue : valueIfFalse picks one of two values.

P5Medium

Short-circuit &&

Show that the right side of && isn't evaluated when the left is false: divide only if the divisor isn't zero.

Input
d = 0
Expected output
ok = false
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int d = 0;
        boolean ok = d != 0 && 100 / d > 5;
        System.out.println("ok = " + ok);
    }
}
ok = false

How it works: because d != 0 is false, Java skips 100 / d, so there's no division by zero.

P6Business problem

Free delivery check

Free delivery if the cart is Rs 499+ or the user is a member. Check a Rs 350 cart for a member.

Input
350, member
Expected output
Free delivery: true
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int cart = 350;
        boolean member = true;
        System.out.println("Free delivery: " + (cart >= 499 || member));
    }
}
Free delivery: true

How it works: || is true if either side is true.

P7Business problem

Notes for an ATM withdrawal

Dispense Rs 2,800 using Rs 500 and Rs 100 notes: print how many of each.

Input
2800
Expected output
500 x 5
100 x 3
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int amount = 2800;
        System.out.println("500 x " + amount / 500);
        System.out.println("100 x " + amount % 500 / 100);
    }
}
500 x 5 100 x 3

How it works: / counts big notes; % gives what's left for smaller ones. % and / have the same precedence and run left to right.

P8Business problem

Loan eligibility in one expression

Eligible if age is 21–60 and income at least Rs 25,000. Check age 34, income 28,000.

Input
34, 28000
Expected output
Eligible: true
Show solution and explanation
public class Main {
    public static void main(String[] args) {
        int age = 34, income = 28000;
        boolean eligible = age >= 21 && age <= 60 && income >= 25000;
        System.out.println("Eligible: " + eligible);
    }
}
Eligible: true

How it works: all three conditions must be true for && to be true. (Illustrative rule.)

Real-world scenario questions (asked in company interviews)

Operator bugs hide in plain sight. Decide your answer first, then open the model answer.

E-commerce · promotionsFresher

Free delivery for everyone

The rule is: free delivery if (cart over ₹399 OR the user is a member) AND the pincode is serviceable. The code says if (cart > 399 || isMember && serviceable). Customers in non-serviceable areas are getting “free delivery” and orders are failing. Why?

The interviewer is checking: do you know that && has higher precedence than ||?

Show a strong answer

Java reads it as cart > 399 || (isMember && serviceable). Any cart over ₹399 passes, whether the pincode is serviceable or not.

  • Fix with explicit brackets: (cart > 399 || isMember) && serviceable.
  • Even better, name the parts: boolean eligible = cart > 399 || isMember; then if (eligible && serviceable).
  • Add tests for each combination of the three conditions (8 cases).

Avoid: relying on memorised precedence in business rules. Brackets document intent.

Data platform · sharding1–3 years

ArrayIndexOutOfBoundsException: Index -2

A service picks one of 8 cache servers with servers[key.hashCode() % 8]. It works for months, then crashes with an index of −2. Someone suggests Math.abs(key.hashCode()) % 8. Is that enough?

The interviewer is checking: do you know that % can be negative and about the Math.abs(Integer.MIN_VALUE) trap?

Show a strong answer

hashCode() can be negative, and Java's % keeps the sign of the left operand, so the index can be −1 to −7.

  • Math.abs is not enough: for Integer.MIN_VALUE, Math.abs returns MIN_VALUE itself (still negative), because +2,147,483,648 doesn't fit in an int. Some real strings have exactly that hash.
  • Use Math.floorMod(key.hashCode(), 8), which always returns 0–7, or (h & 0x7fffffff) % 8.
  • For real systems, consider consistent hashing, so adding a server doesn't move every key.

Avoid saying: “hashCode is always positive.”

Banking · KYC serviceFresher

Slow requests and random NullPointerExceptions

A check reads if (verifyWithBureau(pan) & customer != null & customer.isActive()). Every request makes a slow external bureau call, and some crash with NullPointerException. What would you change?

The interviewer is checking: do you understand short-circuit evaluation and ordering conditions from cheap to expensive?

Show a strong answer

Single & evaluates every operand, so the bureau call always runs, and customer.isActive() runs even when customer is null.

  • Use &&, and order conditions from cheapest and safest to most expensive: customer != null && customer.isActive() && verifyWithBureau(pan).
  • Now the null check protects the method call, and the slow external call only happens for active customers.
  • Measure the drop in bureau calls (and cost) after the change.

Avoid: treating & and && as interchangeable.

Analytics · reportingFresher

Conversion rate always shows 0%

A dashboard shows conversion rate as orders / visitors * 100, with both values as ints. It always shows 0%, even though 340 out of 9,000 visitors ordered. What's the bug, and how would you write it?

The interviewer is checking: do you combine operator order with integer division correctly?

Show a strong answer

Evaluation is left to right for / and * (same precedence). 340 / 9000 in int is 0, and 0 * 100 is 0.

  • Use double arithmetic: orders * 100.0 / visitors gives about 3.78.
  • Or reorder for integers: orders * 100 / visitors gives 3, but watch for overflow on large counts (use long).
  • Handle visitors == 0, and format the result to one or two decimals for display.

Avoid: “Multiply by 100 at the end.” Order and types both matter.