An operator is a special symbol that tells the Java compiler to perform a specific operation on one or more values. The values that an operator acts upon are called operands. Together, an operator and its operands form an expression that evaluates to a result.
int sum = 2 + 5; // 2 and 5 are operands // + is the operator // 2 + 5 is an expression that evaluates to 7 // = is the assignment operator that stores the result in the variable sum
| Operand | Operator | Operand |
|---|---|---|
| 2 | + | 5 |
Operators can be classified by the number of operands they take:
++count, !isValid)a + b, x > y)condition ? value1 : value2)Java provides the following groups of operators:
Arithmetic operators perform mathematical calculations, just like the algebra you learned in school. They work with numeric data types such as int, double, float, and long.
| Operator | Name | Description | Example | Result |
|---|---|---|---|---|
| + | Addition | Adds two values | 5 + 3 | 8 |
| – | Subtraction | Subtracts one value from another | 10 – 4 | 6 |
| * | Multiplication | Multiplies two values | 5 * 4 | 20 |
| / | Division | Divides the left operand by the right operand | 15 / 4 | 3 (integer division) |
| % | Modulus | Returns the remainder of a division | 15 % 4 | 3 |
| ++ | Increment | Increases the value by 1 | x++ or ++x | x + 1 |
| — | Decrement | Decreases the value by 1 | x– or –x | x – 1 |
public class ArithmeticOperators {
public static void main(String[] args) {
int a = 20;
int b = 7;
System.out.println("a + b = " + (a + b)); // Output: a + b = 27
System.out.println("a - b = " + (a - b)); // Output: a - b = 13
System.out.println("a * b = " + (a * b)); // Output: a * b = 140
System.out.println("a / b = " + (a / b)); // Output: a / b = 2 (integer division truncates)
System.out.println("a % b = " + (a % b)); // Output: a % b = 6 (remainder)
// Division with doubles gives the full decimal result
double x = 20.0;
double y = 7.0;
System.out.println("x / y = " + (x / y)); // Output: x / y = 2.857142857142857
}
}
The ++ and -- operators can be placed before (prefix) or after (postfix) a variable. The placement matters when the expression is used inside another statement:
++x) — increments the value first, then uses the new value in the expression.x++) — uses the current value in the expression first, then increments.This is a classic interview question. Understanding the difference will save you from subtle bugs.
public class IncrementDemo {
public static void main(String[] args) {
// Post-increment: uses the value THEN increments
int a = 5;
int b = a++;
System.out.println("Post-increment:");
System.out.println("b = " + b); // Output: b = 5 (a's old value was assigned first)
System.out.println("a = " + a); // Output: a = 6 (a was incremented after)
// Pre-increment: increments THEN uses the value
int x = 5;
int y = ++x;
System.out.println("\nPre-increment:");
System.out.println("y = " + y); // Output: y = 6 (x was incremented first)
System.out.println("x = " + x); // Output: x = 6
// Same rules apply to decrement (-- operator)
int count = 10;
System.out.println("\nPost-decrement: " + count--); // Output: 10 (prints, then decrements)
System.out.println("After post-decrement: " + count); // Output: 9
System.out.println("Pre-decrement: " + --count); // Output: 8 (decrements, then prints)
}
}
Comparison operators compare two values and return a boolean result: either true or false. They are most commonly used in if statements, while loops, and other control flow structures.
| Operator | Name | Description | Example | Result |
|---|---|---|---|---|
| == | Equal to | Returns true if both values are equal | 5 == 5 | true |
| != | Not equal to | Returns true if the values are not equal | 5 != 3 | true |
| > | Greater than | Returns true if the left value is greater than the right | 10 > 5 | true |
| < | Less than | Returns true if the left value is less than the right | 3 < 8 | true |
| >= | Greater than or equal to | Returns true if the left value is greater than or equal to the right | 5 >= 5 | true |
| <= | Less than or equal to | Returns true if the left value is less than or equal to the right | 3 <= 8 | true |
Important: The == operator compares primitive values directly. For objects like String, use the .equals() method instead. Using == on objects compares their memory references, not their content.
public class ComparisonOperators {
public static void main(String[] args) {
int age = 25;
int votingAge = 18;
System.out.println("age == 25: " + (age == 25)); // Output: true
System.out.println("age != votingAge: " + (age != votingAge)); // Output: true
System.out.println("age > votingAge: " + (age > votingAge)); // Output: true
System.out.println("age < 30: " + (age < 30)); // Output: true
System.out.println("age >= 25: " + (age >= 25)); // Output: true
System.out.println("age <= 18: " + (age <= 18)); // Output: false
// Common mistake with Strings
String name1 = new String("Java");
String name2 = new String("Java");
System.out.println("\nname1 == name2: " + (name1 == name2)); // Output: false (different objects)
System.out.println("name1.equals(name2): " + name1.equals(name2)); // Output: true (same content)
}
}
Assignment operators store a value in a variable. The basic assignment operator is =. Java also provides compound assignment operators that combine an arithmetic operation with assignment, making your code shorter and more readable.
| Operator | Name | Equivalent To | Example (if x = 10) | Result |
|---|---|---|---|---|
| = | Assign | x = value | x = 5 | x is 5 |
| += | Add and assign | x = x + value | x += 3 | x is 13 |
| -= | Subtract and assign | x = x - value | x -= 4 | x is 6 |
| *= | Multiply and assign | x = x * value | x *= 2 | x is 20 |
| /= | Divide and assign | x = x / value | x /= 5 | x is 2 |
| %= | Modulus and assign | x = x % value | x %= 3 | x is 1 |
public class AssignmentOperators {
public static void main(String[] args) {
int score = 100;
System.out.println("Initial score: " + score); // Output: 100
score += 10; // score = score + 10
System.out.println("After += 10: " + score); // Output: 110
score -= 25; // score = score - 25
System.out.println("After -= 25: " + score); // Output: 85
score *= 2; // score = score * 2
System.out.println("After *= 2: " + score); // Output: 170
score /= 5; // score = score / 5
System.out.println("After /= 5: " + score); // Output: 34
score %= 10; // score = score % 10
System.out.println("After %= 10: " + score); // Output: 4
}
}
Logical operators are used to combine multiple boolean expressions into a single result. They are essential for building complex conditions in if statements and loops. Every professional Java application uses logical operators extensively.
| Operator | Name | Description | Example | Result |
|---|---|---|---|---|
| && | Logical AND | Returns true only if both conditions are true | true && false | false |
| || | Logical OR | Returns true if at least one condition is true | true || false | true |
| ! | Logical NOT | Reverses the boolean value | !true | false |
Truth tables show every possible outcome for logical operators. Memorizing these will help you write correct conditions on the first try.
AND (&&) Truth Table:
| A | B | A && B |
|---|---|---|
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
OR (||) Truth Table:
| A | B | A || B |
|---|---|---|
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false |
public class LogicalOperators {
public static void main(String[] args) {
int age = 25;
boolean hasLicense = true;
boolean isInsured = false;
// AND (&&): Both conditions must be true
boolean canDrive = (age >= 16) && hasLicense;
System.out.println("Can drive: " + canDrive); // Output: true (both conditions are true)
// OR (||): At least one condition must be true
boolean hasDocuments = hasLicense || isInsured;
System.out.println("Has documents: " + hasDocuments); // Output: true (hasLicense is true)
// NOT (!): Reverses the boolean value
boolean isNotInsured = !isInsured;
System.out.println("Is NOT insured: " + isNotInsured); // Output: true
// Combining multiple logical operators
boolean canRentCar = (age >= 21) && hasLicense && isInsured;
System.out.println("Can rent car: " + canRentCar); // Output: false (isInsured is false)
// Real-world example: form validation
String username = "folau";
String password = "secret123";
boolean isValidLogin = (username != null && !username.isEmpty())
&& (password != null && password.length() >= 8);
System.out.println("Valid login: " + isValidLogin); // Output: true
}
}
Java's && and || operators use short-circuit evaluation, meaning they stop evaluating as soon as the result is determined:
&& (AND): If the left side is false, the right side is never evaluated because the result will always be false.|| (OR): If the left side is true, the right side is never evaluated because the result will always be true.This is not just a performance optimization — it is a defensive coding technique. You can use it to avoid NullPointerException errors:
public class ShortCircuitDemo {
public static void main(String[] args) {
// Short-circuit prevents NullPointerException
String name = null;
// Without short-circuit, this would crash with NullPointerException:
// boolean result = name.length() > 3; // CRASH! name is null
// With short-circuit AND, the second condition is skipped when name is null
boolean isLongName = (name != null) && (name.length() > 3);
System.out.println("Is long name: " + isLongName); // Output: false (safe!)
// Short-circuit OR: provides a default when first condition is true
boolean hasPermission = true;
boolean isAdmin = false;
// isAdmin is never checked because hasPermission is already true
boolean canAccess = hasPermission || isAdmin;
System.out.println("Can access: " + canAccess); // Output: true
// Practical example: safe method call chain
String email = null;
boolean isValidEmail = (email != null) && email.contains("@") && email.contains(".");
System.out.println("Valid email: " + isValidEmail); // Output: false (safe, no NPE)
}
}
Bitwise operators work on individual bits (0s and 1s) of integer values. While you may not use them daily, they appear in performance-critical code, permission systems, and low-level operations. They are also commonly asked about in interviews.
| Operator | Name | Description | Example (a=5, b=3) | Result |
|---|---|---|---|---|
| & | Bitwise AND | Sets each bit to 1 if both bits are 1 | 5 & 3 (0101 & 0011) | 1 (0001) |
| | | Bitwise OR | Sets each bit to 1 if at least one bit is 1 | 5 | 3 (0101 | 0011) | 7 (0111) |
| ^ | Bitwise XOR | Sets each bit to 1 if only one bit is 1 | 5 ^ 3 (0101 ^ 0011) | 6 (0110) |
| ~ | Bitwise NOT | Flips all bits (inverts) | ~5 (~0101) | -6 |
| << | Left shift | Shifts bits left, fills with 0s (multiplies by 2) | 5 << 1 (0101 << 1) | 10 (1010) |
| >> | Right shift | Shifts bits right, preserves sign (divides by 2) | 5 >> 1 (0101 >> 1) | 2 (0010) |
public class BitwiseOperators {
public static void main(String[] args) {
int a = 5; // binary: 0101
int b = 3; // binary: 0011
System.out.println("a & b = " + (a & b)); // Output: 1 (0001)
System.out.println("a | b = " + (a | b)); // Output: 7 (0111)
System.out.println("a ^ b = " + (a ^ b)); // Output: 6 (0110)
System.out.println("~a = " + (~a)); // Output: -6
System.out.println("a << 1 = " + (a << 1)); // Output: 10 (1010) - multiplied by 2
System.out.println("a >> 1 = " + (a >> 1)); // Output: 2 (0010) - divided by 2
// Practical example: checking if a number is even or odd using bitwise AND
int number = 42;
if ((number & 1) == 0) {
System.out.println(number + " is even"); // Output: 42 is even
} else {
System.out.println(number + " is odd");
}
// Practical example: permission flags
int READ = 0b001; // 1
int WRITE = 0b010; // 2
int EXECUTE = 0b100; // 4
int userPermissions = READ | WRITE; // Combine permissions: 011 (3)
boolean canRead = (userPermissions & READ) != 0;
boolean canWrite = (userPermissions & WRITE) != 0;
boolean canExec = (userPermissions & EXECUTE) != 0;
System.out.println("Can read: " + canRead); // Output: true
System.out.println("Can write: " + canWrite); // Output: true
System.out.println("Can execute: " + canExec); // Output: false
}
}
The ternary operator is Java's only operator that takes three operands. It is a compact alternative to an if-else statement and is useful when you need to assign a value based on a condition.
Syntax:
variable = (condition) ? valueIfTrue : valueIfFalse;
Think of it as asking a yes-or-no question: "Is this condition true? If yes, use the first value. If no, use the second value."
public class TernaryOperator {
public static void main(String[] args) {
// Basic example
int temperature = 35;
String weather = (temperature > 30) ? "Hot" : "Cool";
System.out.println("Weather: " + weather); // Output: Hot
// Equivalent if-else (ternary is more concise)
// String weather;
// if (temperature > 30) {
// weather = "Hot";
// } else {
// weather = "Cool";
// }
// Assigning max value
int a = 15;
int b = 22;
int max = (a > b) ? a : b;
System.out.println("Max: " + max); // Output: 22
// Checking for null safely
String name = null;
String displayName = (name != null) ? name : "Guest";
System.out.println("Hello, " + displayName); // Output: Hello, Guest
// Nested ternary (use sparingly - readability suffers)
int score = 85;
String grade = (score >= 90) ? "A"
: (score >= 80) ? "B"
: (score >= 70) ? "C"
: (score >= 60) ? "D" : "F";
System.out.println("Grade: " + grade); // Output: B
// Practical: formatting output
int itemCount = 1;
String message = "You have " + itemCount + " item" + (itemCount != 1 ? "s" : "") + " in your cart.";
System.out.println(message); // Output: You have 1 item in your cart.
itemCount = 5;
message = "You have " + itemCount + " item" + (itemCount != 1 ? "s" : "") + " in your cart.";
System.out.println(message); // Output: You have 5 items in your cart.
}
}
The instanceof operator checks whether an object is an instance of a specific class, subclass, or interface. It returns true or false. This operator is essential when working with inheritance and polymorphism, where you need to determine an object's actual type at runtime before performing type-specific operations.
public class InstanceofOperator {
public static void main(String[] args) {
// Basic type checking
String name = "Folau";
boolean isString = name instanceof String;
System.out.println("name instanceof String: " + isString); // Output: true
// Checking with inheritance
Object obj = "Hello World";
System.out.println("obj instanceof String: " + (obj instanceof String)); // Output: true
System.out.println("obj instanceof Object: " + (obj instanceof Object)); // Output: true
// Null check - instanceof always returns false for null
String nullStr = null;
System.out.println("null instanceof String: " + (nullStr instanceof String)); // Output: false
// Practical example: processing different types
Object[] items = {"Hello", 42, 3.14, true, new int[]{1, 2, 3}};
for (Object item : items) {
if (item instanceof String) {
System.out.println("String: " + item);
} else if (item instanceof Integer) {
System.out.println("Integer: " + item);
} else if (item instanceof Double) {
System.out.println("Double: " + item);
} else if (item instanceof Boolean) {
System.out.println("Boolean: " + item);
} else {
System.out.println("Other type: " + item.getClass().getSimpleName());
}
}
// Output:
// String: Hello
// Integer: 42
// Double: 3.14
// Boolean: true
// Other type: int[]
}
}
Since Java 16, you can use pattern matching with instanceof to cast and assign in a single step, eliminating the need for a separate cast statement:
public class PatternMatchingInstanceof {
public static void main(String[] args) {
Object value = "Hello, Java!";
// Before Java 16: traditional instanceof + cast
if (value instanceof String) {
String str = (String) value;
System.out.println("Length: " + str.length());
}
// Java 16+: pattern matching instanceof (cleaner)
if (value instanceof String str) {
System.out.println("Length: " + str.length()); // Output: Length: 12
}
// Works with negation too
Object number = 42;
if (!(number instanceof String str)) {
System.out.println("Not a string"); // Output: Not a string
}
}
}
When multiple operators appear in a single expression, Java uses operator precedence to determine the order of evaluation. Operators with higher precedence are evaluated first. When operators have the same precedence, associativity (left-to-right or right-to-left) determines the order.
You do not need to memorize this entire table. The practical rule is: use parentheses () to make your intent clear. Parentheses always have the highest precedence and make code more readable.
| Precedence | Operator | Description | Associativity |
|---|---|---|---|
| 1 (highest) | () [] . | Parentheses, array access, member access | Left to right |
| 2 | ++ -- ! ~ | Unary operators (prefix increment, NOT, bitwise NOT) | Right to left |
| 3 | * / % | Multiplication, division, modulus | Left to right |
| 4 | + - | Addition, subtraction | Left to right |
| 5 | << >> | Bitwise shift | Left to right |
| 6 | < <= > >= instanceof | Relational operators | Left to right |
| 7 | == != | Equality operators | Left to right |
| 8 | & | Bitwise AND | Left to right |
| 9 | ^ | Bitwise XOR | Left to right |
| 10 | | | Bitwise OR | Left to right |
| 11 | && | Logical AND | Left to right |
| 12 | || | Logical OR | Left to right |
| 13 | ? : | Ternary | Right to left |
| 14 (lowest) | = += -= *= /= %= | Assignment operators | Right to left |
public class OperatorPrecedence {
public static void main(String[] args) {
// Multiplication is evaluated before addition (higher precedence)
int result1 = 2 + 3 * 4;
System.out.println("2 + 3 * 4 = " + result1); // Output: 14 (not 20)
// Parentheses override default precedence
int result2 = (2 + 3) * 4;
System.out.println("(2 + 3) * 4 = " + result2); // Output: 20
// Logical AND (&&) has higher precedence than logical OR (||)
boolean result3 = true || false && false;
System.out.println("true || false && false = " + result3); // Output: true
// Evaluated as: true || (false && false) -> true || false -> true
// Use parentheses to change the order
boolean result4 = (true || false) && false;
System.out.println("(true || false) && false = " + result4); // Output: false
// Complex expression - parentheses make intent clear
int x = 10, y = 5, z = 3;
// Unclear without parentheses:
int unclear = x + y * z - x / y;
// Clear with parentheses:
int clear = x + (y * z) - (x / y);
System.out.println("Result: " + unclear); // Output: 23
System.out.println("Result: " + clear); // Output: 23 (same, but readable)
}
}
In real-world applications, you will frequently combine multiple types of operators in a single block of code. The following examples demonstrate how operators work together in scenarios you might encounter on the job.
/**
* Example 1: Grade Calculator
* Combines arithmetic, comparison, logical, and ternary operators.
*/
public class GradeCalculator {
public static void main(String[] args) {
int exam1 = 88;
int exam2 = 76;
int exam3 = 95;
int homework = 82;
// Arithmetic operators: calculate weighted average
double finalGrade = (exam1 + exam2 + exam3) / 3.0 * 0.7 + homework * 0.3;
System.out.println("Final grade: " + finalGrade); // Output: 85.21666...
// Comparison + ternary: determine letter grade
String letterGrade = (finalGrade >= 90) ? "A"
: (finalGrade >= 80) ? "B"
: (finalGrade >= 70) ? "C"
: (finalGrade >= 60) ? "D" : "F";
System.out.println("Letter grade: " + letterGrade); // Output: B
// Logical operators: check honors eligibility
boolean noFailingExams = (exam1 >= 60) && (exam2 >= 60) && (exam3 >= 60);
boolean isHonors = (finalGrade >= 85) && noFailingExams;
System.out.println("Honors: " + isHonors); // Output: true
// Assignment operator: apply bonus
double bonus = isHonors ? 2.0 : 0.0;
finalGrade += bonus;
System.out.println("Final grade with bonus: " + finalGrade); // Output: 87.21666...
}
}
/**
* Example 2: User Registration Validation
* Demonstrates real-world use of logical, comparison, and instanceof operators.
*/
public class RegistrationValidator {
public static void main(String[] args) {
String username = "john_doe";
String password = "Secure@123";
String email = "john@example.com";
int age = 20;
// Validate username: not null, not empty, between 3-20 characters
boolean isValidUsername = (username != null)
&& (!username.isEmpty())
&& (username.length() >= 3)
&& (username.length() <= 20);
// Validate password: at least 8 characters, contains a digit
boolean hasDigit = false;
for (char c : password.toCharArray()) {
if (c >= '0' && c <= '9') { // Comparison operators on char values
hasDigit = true;
break;
}
}
boolean isValidPassword = (password != null) && (password.length() >= 8) && hasDigit;
// Validate email: contains @ and a dot after @
boolean isValidEmail = (email != null)
&& email.contains("@")
&& (email.indexOf('.', email.indexOf('@')) > 0);
// Validate age: must be 18 or older
boolean isValidAge = (age >= 18);
// All fields must be valid for registration to succeed
boolean canRegister = isValidUsername && isValidPassword && isValidEmail && isValidAge;
// Ternary operator for the final message
String status = canRegister ? "Registration successful!" : "Registration failed. Please fix errors.";
System.out.println(status); // Output: Registration successful!
// Detailed feedback using logical NOT
if (!isValidUsername) System.out.println("- Invalid username");
if (!isValidPassword) System.out.println("- Invalid password");
if (!isValidEmail) System.out.println("- Invalid email");
if (!isValidAge) System.out.println("- Must be 18 or older");
}
}
/**
* Example 3: Simple Shopping Cart
* Demonstrates arithmetic, comparison, ternary, and compound assignment operators.
*/
public class ShoppingCart {
public static void main(String[] args) {
double itemPrice = 29.99;
int quantity = 3;
double taxRate = 0.08; // 8% tax
double discountThreshold = 50.0;
double discountRate = 0.10; // 10% discount
// Calculate subtotal using arithmetic operators
double subtotal = itemPrice * quantity;
System.out.println("Subtotal: $" + subtotal); // Output: $89.97
// Apply discount if subtotal exceeds threshold (comparison + ternary)
double discount = (subtotal >= discountThreshold) ? subtotal * discountRate : 0.0;
System.out.println("Discount: $" + discount); // Output: $8.997
// Compound assignment: subtract discount from subtotal
subtotal -= discount;
System.out.println("After discount: $" + subtotal); // Output: $80.973
// Calculate tax
double tax = subtotal * taxRate;
System.out.println("Tax: $" + tax); // Output: $6.47784
// Compound assignment: add tax to subtotal
subtotal += tax;
System.out.printf("Total: $%.2f%n", subtotal); // Output: Total: $87.45
// Check if free shipping applies (logical operator)
boolean isMember = true;
boolean freeShipping = (subtotal > 75.0) || isMember;
System.out.println("Free shipping: " + freeShipping); // Output: true
}
}
Operators are the building blocks of every Java expression. Here is a quick recap of what we covered:
| Operator Category | Operators | Primary Use |
|---|---|---|
| Arithmetic | + - * / % ++ -- | Mathematical calculations |
| Comparison | == != > < >= <= | Comparing values, producing booleans |
| Assignment | = += -= *= /= %= | Storing and updating values in variables |
| Logical | && || ! | Combining boolean conditions |
| Bitwise | & | ^ ~ << >> | Bit-level operations, flags, permissions |
| Ternary | ? : | Inline conditional value assignment |
| Instanceof | instanceof | Runtime type checking |
Key takeaways:
++x) and post-increment (x++) — it is a common interview question.== for primitive comparisons and .equals() for object comparisons.&& and ||) to write null-safe conditions.