An operator is a symbol that takes a value (operand) and creates a new value. Java's operators look familiar because they originated from C/C++, but they have pitfalls such as object comparison (== vs .equals()) and integer/real division. We summarize in this section.
Learning Objectives
- Arithmetic, comparison, logic, bit, ternary, and increment/decrement operators are used separately.
- Understand the left-to-right evaluation rules of
+when combiningString - Clearly know the difference between
==and.equals() - Understand what short-circuit evaluation (
&&/||) is
Key concepts
1) Arithmetic/Comparison/Logic
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a / b); //3 (integer division!)
System.out.println(a % b); // 1
System.out.println(a > b); // true
System.out.println(a == 10 && b > 0); // true
2) Increment/decrement operator
int x = 5;
System.out.println(x++); //5 (increases after use)
System.out.println(++x); //7 (use after increase)
x++ and ++x have different result values. Be careful because readability will decrease if you mix them in a formula.
3) Ternary operator
int score = 75;
String result = (score >= 60) ? "passed" : "failed";
It is a short form of if/else. This is useful when setting values in one line.
4) == vs .equals()
String a = "hello";
String b = new String("hello");
System.out.println(a == b); //false (references are different)
System.out.println(a.equals(b)); //true (content is the same)
Always compare objects (especially String/Integer/List, etc.) with .equals(). == is for checking equality between primitives or references.
5) Bitwise operators
int mask = 0b1010;
int val = 0b1100;
System.out.println(mask & val); // 8 (AND)
System.out.println(mask | val); // 14 (OR)
System.out.println(mask ^ val); // 6 (XOR)
System.out.println(mask << 1); //20 (left shift)
It is encountered in places such as flag handling, hashing, and encryption.
See as example
Example 1 — Arithmetic.java: Arithmetic and division pitfalls
public class Arithmetic {
public static void main(String[] args) {
int a = 17, b = 5;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b); //Integer division
System.out.println(a % b);
System.out.println((double) a / b); //Real division
}
}
Execution result
22
12
85
3
2
3.4
Note: int / int is always an integer. If you need a real number, cast one side as double.
Example 2 — LogicAndTernary.java: Comparison, logic, ternary
public class LogicAndTernary {
public static void main(String[] args) {
int score = 75;
boolean passed = score >= 60;
System.out.println("Passed?" + passed);
String grade = (score >= 90) ? "A"
: (score >= 80) ? "B"
: (score >= 70) ? "C"
: (score >= 60) ? "D"
: "F";
System.out.println("Rating:" + grade);
boolean ok = score > 0 && score <= 100;
System.out.println("Effective range?" + ok);
}
}
Execution result
Passed? true
Grade: C
Effective range? true
Note: && and || are short-circuit. Safe null check is possible like a != null && a.length() > 0.
Example 3 — EqualsVsEqEq.java: Reference comparison vs content comparison
public class EqualsVsEqEq {
public static void main(String[] args) {
String a = "Java";
String b = "Java";
String c = new String("Java");
System.out.println("a == b : " + (a == b));
System.out.println("a == c : " + (a == c));
System.out.println("a.equals(c) : " + a.equals(c));
Integer x = 100;
Integer y = 100;
Integer z = 200;
Integer w = 200;
System.out.println("100==100? " + (x == y)); //true as cache
System.out.println("200==200? " + (z == w)); //out of cache, false
System.out.println("equals : " + z.equals(w));
}
}
Execution result
a == b : true
a == c : false
a.equals(c) : true
100==100? true
200==200? false
equals : true
Note: Integer caches only -128 ~ 127, causing == to accidentally become true. Object is always .equals().
Example 4 — Bitwise.java: Bitwise operations
public class Bitwise {
public static void main(String[] args) {
int a = 0b1010;
int b = 0b1100;
System.out.printf("a & b = %d (%s)%n", a & b, Integer.toBinaryString(a & b));
System.out.printf("a | b = %d (%s)%n", a | b, Integer.toBinaryString(a | b));
System.out.printf("a ^ b = %d (%s)%n", a ^ b, Integer.toBinaryString(a ^ b));
System.out.printf("~a = %d%n", ~a);
System.out.printf("a<<1 = %d%n", a << 1);
System.out.printf("a>>1 = %d%n", a >> 1);
}
}
Execution result
a & b = 8 (1000)
a | b = 14 (1110)
a ^ b = 6 (110)
~a = -11
a<<1 = 20
a>>1 = 5
Note: ~a is -(a+1). That's because of 2's complement representation.
Common Mistakes
- Use
==for object comparison → Replace with.equals() - Calculate
int a = 1/2;without knowing it is 0 - Mixing the postfix
i++in the if condition results in confusing results. - Confusion between
&&and&(the former evaluates short circuit, the latter always evaluates both sides) - A bug where
==sometimes accidentally works because of theIntegercache.
Cleanup
- Consciously distinguish between integer and real number operations
- Object comparison is always
.equals() - Bit operations are useful in special situations such as flags and hashes.
- Short circuit evaluation is a key tool for null checking
Try it yourself
cd 01_Basics/03_Operators-and_Expressions/src
javac Arithmetic.java
java Arithmetic