Java Operators

Dilip PatelDilip Patel
30 min read

In this article, we'll take a look at Java's operators. Java has a significant number of operators, and with luck, they're all pretty much familiar to you. There are some of these though that we should probably take a little extra look at. Notice that the precedence order for most of Java's operators, especially the multiplicative ones like multiply, divide, and remainder, will be executed before addition and subtraction.

Introduction

An operator is a symbol that performs a specific operation on one, two, or three operands, producing a result. The type of the operator and its operands determine the kind of operation performed and the type of result produced.

Operators in Java can be categorized based on two criteria:

  1. Number of Operands:

    • Unary Operators: Operate on a single operand.

    • Binary Operators: Operate on two operands.

    • Ternary Operators: Operate on three operands.

  2. Type of Operation:

    • Assignment Operators: Assign values to variables.

    • Arithmetic Operators: Perform mathematical operations.

    • Relational Operators: Compare two values.

    • Logical Operators: Perform logical operations.

    • Bitwise Operators: Perform operations on individual bits.

    • Conditional Operators: Evaluate expressions based on conditions.

    • Type Comparison Operators: Compare types of objects.

OperatorDescription
Arithmetic
+Addition
-Subtraction
*Multiplication
/Division
%Remainder
Unary
++Increment (increase by 1)
--Decrement (decrease by 1)
+Positive (unary plus)
-Negative (unary minus)
!Logical NOT
~Bitwise NOT
Relational
\==Equal to
!=Not equal to
<Less than
>Greater than
<=Less than or equal to
>=Greater than or equal to
Logical
&&Logical AND
Logical OR
Conditional
? :Ternary operator (conditional expression)
Bitwise
&Bitwise AND
Bitwise AND
^Bitwise XOR
<<Left shift
>>Right shift
>>>Unsigned right shift
Assignment
\=Simple assignment
+=Addition assignment
-=Subtraction assignment
*=Multiplication assignment
/=Division assignment
%=Modulus assignment
&=Bitwise AND assignment
Bitwise OR assignment
^=Bitwise XOR assignment
<<=Left shift assignment
>>=Right shift assignment
>>>=Unsigned right shift assignment
Other
->Arrow operator (used in lambda expressions)
::Double colon operator (used for method references)
newInstance creation operator
instanceofType comparison operator
+String concatenation operator

Key Concepts

First, we need to dive into these key concepts. The first of these is the idea of an expression. Then the next one is the idea of an L-value which is a particular kind of expression that we can actually assign a value to. And then finally, we need to look at side effects, Operator precedence and evaluation.

Expressions

An expression is a combination of values, variables, operators, and function calls that produces a result value. An expression in Java is a construct that evaluates to a single value. It can be as simple as a literal value or as complex as a combination of variables, operators, and method calls. Let's break down the concept of expressions in more detail.

  • Can be simple (literals) or complex (with operations)

  • Have a value and a type

  • Do not have storage

  • Cannot be assigned to

Simple Expression

The simplest form of a pure expression:

2 + 3

These literals have a value and a type, but they do not have storage. This means you cannot assign a new value to them directly.

Literal Expressions

The simplest form of an expression is a literal value. For example:

Individual numbers are also expressions:

2

3

Both 2 and 3 are literal expressions.

  • 2 is a literal expression of type int.

  • "Hello" is a literal expression of type String.

  • 3.14 is a literal expression of type double.

Compound Expressions

When we think of expressions, we often think of more complex constructs that involve operations. For example:

  • 2 + 3 is an arithmetic expression.

  • a * b - c is a compound arithmetic expression.

  • x > y is a relational expression.

In these cases, the expression combines multiple operands (like 2 and 3) with operators (like +). The result of the expression has a value and a type. For instance, 2 + 3 evaluates to 5, which is of type int.

Value and Type

Every expression in Java has a value and a type:

  • Value: The result of evaluating the expression. For example, the value of 2 + 3 is 5.

  • Type: The data type of the result. For example, the type of 2 + 3 is int.

No Storage

Expressions do not have storage. This means you cannot assign a value to an expression directly. For example, you cannot do something like (2 + 3) = 5. The expression 2 + 3 evaluates to 5, but it does not have a memory location where you can store a value.

Examples of Expressions

  1. Expressions with Operations

     2 + 3 * 4
    

    This expression combines multiple operations.

  2. Arithmetic Expression:

     int result = 2 + 3; // result is 5
    

    Here, 2 + 3 is an arithmetic expression that evaluates to 5.

  3. Relational Expression:

     boolean isGreater = 5 > 3; // isGreater is true
    

    Here, 5 > 3 is a relational expression that evaluates to true.

  4. Logical Expression:

     boolean isTrue = (5 > 3) && (2 < 4); // isTrue is true
    

    Here, (5 > 3) && (2 < 4) is a logical expression that evaluates to true.

  5. Method Call Expression:

     int length = "Hello".length(); // length is 5
    

    Here, "Hello".length() is a method call expression that evaluates to 5.

Properties of Expressions

ValueResult of the expression
TypeData type of the result (e.g., int, float)
StorageNo storage allocated

Expression Example: 2 + 3

ValueTypeCan assign to it?
5intNo

No Assignment to Expressions

You cannot assign a value to an expression:

(2 + 3) = 6  // This is invalid!

Expressions have values, but no storage location.

Expression vs. Variable

Expression: 2 + 3

Variable: x = 5

An expression has a value but no storage, while a variable has both value and storage.

L-values

In Java, an L-value (locator value) is an expression that refers to a memory location and allows us to assign a value to it. The term "L-value" stands for "left-hand side value" because these expressions can appear on the left side of an assignment statement.

  • Refers to a memory location

  • Allows us to assign a value to it

  • L-values represent expressions with storage locations

  • Can appear on the left side of an assignment

  • They can be assigned new values

  • It aids in avoiding common errors related to variable assignment

Understanding L-values

An L-value is an expression that has both a value and a storage location. This means that you can assign a new value to it. Common examples of L-values include variables and array elements.

Examples of L-values

  1. Simple Variables:

     int x = 5; // 'x' is an L-value
     x = 10;    // 'x' can be assigned a new value
    

    Here, x is a simple variable that refers to a memory location where the integer value is stored. Since x has a storage location, it is an L-value, and we can assign a new value to it.

  2. Array Elements:

     int[] arr = {1, 2, 3, 4};
     arr[2] = 10; // 'arr[2]' is an L-value
    

    In this example, arr[2] refers to the element at index 2 of the array arr. This element has a storage location, so arr[2] is an L-value, and we can assign a new value to it.

Non-L-values

Expressions that do not refer to a storage location are not L-values. These expressions cannot appear on the left side of an assignment statement. Examples include literals and the results of arithmetic operations.

  1. Literals:

     5 = x; // Error: '5' is not an L-value
    

    Here, 5 is a literal and does not have a storage location. Therefore, it is not an L-value, and we cannot assign a value to it.

  2. Results of Arithmetic Operations:

     int result = 2 + 3;
     (2 + 3) = 5; // Error: '2 + 3' is not an L-value
    

    The expression 2 + 3 evaluates to 5, but it does not have a storage location. Hence, it is not an L-value, and we cannot assign a value to it.

L-values and R-values

In Java, expressions can be classified as L-values or R-values (right-hand side values). An R-value is any expression that has a value but does not necessarily have a storage location. All L-values can be used as R-values, but not all R-values can be used as L-values.

  • L-value: Has a storage location

  • R-value: Has a value, but not necessarily a storage location

All L-values can be R-values, but not vice versa.

Example:

int x = 5;    // 'x' is an L-value and can be used as an R-value
int y = x + 2; // 'x' is used as an R-value here

In this example, x is an L-value because it refers to a storage location. When used in the expression x + 2, x is treated as an R-value because we are using its value.

Side Effects

In Java, a side effect occurs when an expression modifies some state or value outside its local environment. This typically involves changing the value of a variable or altering the state of an object. Side effects are an important concept to understand because they can impact the behaviour and outcome of your code in ways that are not immediately obvious.

Understanding Side Effects

A side effect is any operation that modifies the state of the program. This can include:

  • Assigning a value to a variable.

  • Modifying an object’s state.

  • Performing I/O operations.

Examples of Side Effects

  1. Simple Assignment:

     int x = 3; // Assigns the value 3 to the variable x
    

    In this example, the assignment x = 3 changes the value of the variable x to 3. This is a side effect because it modifies the state of x.

  2. Pre-Increment Operator:

     int i = 5;
     int j = ++i; // Pre-increment: i is incremented to 6, then j is assigned the value 6
    

    Here, the pre-increment operator ++i increments the value of i by 1 before the value is used in the expression. The side effect is the modification of i from 5 to 6.

  3. Post-Increment Operator:

     int i = 5;
     int j = i++; // Post-increment: j is assigned the value 5, then i is incremented to 6
    

    In this case, the post-increment operator i++ increments the value of i by 1 after the value is used in the expression. The side effect is the modification of i from 5 to 6, but j is assigned the original value of i before the increment.

Conditions for Side Effects

For a side effect to occur, there must be an L-value involved. An L-value is an expression that refers to a memory location and allows us to assign a value to it. Without an L-value, an expression cannot have a side effect.

Example:

int x = 5;
int y = 10;
int result = (x + y); // No side effect, as (x + y) is not an L-value

In this example, the expression (x + y) evaluates to 15, but it does not modify any state or value, so there is no side effect.

Operator Precedence

Operator precedence determines the order in which operators are evaluated in expressions. For example, ++ regardless of whether it's the pre-increment or the post-increment has the highest precedence, followed by multiplication (*), followed by the minus operation (-), followed by the equality test (==), followed by assignment (=).

PrecedenceOperator
Highest++ (pre/post increment)
* (multiplication)
- (subtraction)
== (equality test)
Lowest= (assignment)

Operand Evaluation

Operands in Java are evaluated from left to right but this is done before we apply the operation. Side effects take place during the operands evaluation.

Example:

int x = 5;
int y = 10;
int result = x + y * 2; // result is 25, multiplication has higher precedence than addition

Let's explore various operators in Java along with example programs:

1) Assignment Operators

The assignment operator (=) is used to assign a value to a variable.

  • It is a binary operator (takes two operands)

  • Right-hand operand's value is assigned to the left-hand operand

  • Left-hand operand must be a variable

Example Program:

public class AssignmentOperatorTest {
    public static void main(String[] args) {
        int x = 4;
        int y = 2;

        x += y;
        System.out.println("+=   " + x); // 6

        x = 4; y = 2;
        x -= y;
        System.out.println("-=   " + x); // 2

        x = 4; y = 2;
        x *= y;
        System.out.println("*=   " + x); // 8

        x = 4; y = 2;
        x /= y;
        System.out.println("/=   " + x); // 2
    }
}

Assignment Compatibility

Java ensures assignment compatibility between operands:

  • Right-hand value must be compatible with left-hand variable type

  • Compile-time error occurs if incompatible

  • For reference variables, runtime ClassCastException may occur

int x = 5;     // Valid
int y = "5";   // Compile-time error
Object obj = new Integer(5);
String str = (String)obj;  // Runtime ClassCastException

2) Arithmetic Operators

Java arithmetic operators work the same way as they do in mathematics. Multiply (*) and divide (/) are pretty much as you would expect and we're not going to go into those in any more detail. However, the remainder operator (%), sometimes wrongly called the modulus operator, we will spend a little extra time on later on in this artcle. Add (+) and subtract (-) should also be essentially familiar.

  • +: Addition (can be used for string concatenation as well)

  • -: Subtraction

  • *: Multiplication

  • /: Division

  • %: Remainder

Examples:

int x = 10;
int y = 3;
int sum = x + y; // sum is 13
int diff = x - y; // diff is 7
int prod = x * y; // prod is 30
int quot = x / y; // quot is 3
int rem = x % y; // rem is 1

Unary Arithmetic Operators

Unary arithmetic operators operate on a single operand. Here are the unary arithmetic operators available in Java:

OperatorDescription
+Unary plus (indicates positive value)
-Unary minus (negates an expression)
++Increment (increases value by 1)
--Decrement (decreases value by 1)
!Logical complement (inverts boolean value)
~Bitwise inversion

Unary Arithmetic Operators: Examples

int a = 5;
int b = -a; // b is -5
boolean flag = true;
flag = !flag; // flag is false

System.out.println(++a);    // Pre-increment: 6
System.out.println(b--);    // Post-decrement: -5 (b becomes -6 after this line)

Binary Arithmetic Operators

Binary arithmetic operators operate on two operands. Here are the binary arithmetic operators available in Java:

OperatorDescription
+Addition – Adds values on either side of the operator
-Subtraction – Subtracts right-hand operand from left-hand operand
*Multiplication – Multiplies values on either side of the operator
/Division – Divides left-hand operand by right-hand operand
%Modulus – Divides left-hand operand by right-hand operand and returns the remainder

Binary Arithmetic Operators: Examples

int a = 10, b = 3;
System.out.println(a + b);  // Addition: 13
System.out.println(a - b);  // Subtraction: 7
System.out.println(a * b);  // Multiplication: 30
System.out.println(a / b);  // Division: 3
System.out.println(a % b);  // Modulus: 1

Note: Integer division (a / b) truncates the decimal part.

Remainder Operator

The % or remainder operator in Java is used to find the remainder of the division of one number by another. The remainder operation is not the same as the modulus operation, although they are often confused due to their similarities.

Key Differences Between Remainder and Modulus

  1. Sign of the Result:

    • Remainder: The sign of the result is the same as the sign of the left-hand operand (dividend).

    • Modulus: The sign of the result is always positive, regardless of the signs of the operands.

  2. Behaviour with Negative Numbers:

    • Remainder: When dealing with negative numbers, the remainder operation takes the sign of the left-hand operand.

    • Modulus: The modulus operation always returns a non-negative result.

Examples

Let's consider the following examples to illustrate the behavior of the remainder operator:

int a = 7;
int b = -3;
int rem1 = a % b; // rem1 is 1
int rem2 = -a % b; // rem2 is -1
  1. Example 1: a % b

    • a = 7

    • b = -3

    • Calculation: 7 % -3

    • Division: 7 / -3 results in -2 (integer division)

    • Remainder: 7 - (-3 * -2) = 7 - 6 = 1

    • Result: rem1 = 1

    • Explanation: The remainder is 1 because the sign of the result is the same as the sign of 7 (positive).

  2. Example 2: -a % b

    • a = 7

    • b = -3

    • Calculation: -7 % -3

    • Division: -7 / -3 results in 2 (integer division)

    • Remainder: -7 - (-3 * 2) = -7 - 6 = -1

    • Result: rem2 = -1

    • Explanation: The remainder is -1 because the sign of the result is the same as the sign of -7 (negative).

Key points:

  1. The remainder operator % in Java returns the remainder of the division of two numbers.

  2. The sign of the result is determined by the sign of the left-hand operand (dividend).

  3. This behaviour is different from the modulus operation, which always returns a non-negative result.

In Java, the + operator is versatile and serves not only for arithmetic addition but also for string concatenation. This operator allows you to combine strings and other data types into a single string. Let's delve into the details of how string concatenation works in Java.

String Concatenation Operator

1. Concatenating Two Strings

When you have two strings and you want to combine them, you can use the + operator. Here’s an example:

String str1 = "Hello";
String str2 = " World";
String str3 = str1 + str2; // Assigns "Hello World" to str3

In this example:

  • str1 contains "Hello".

  • str2 contains " World".

  • Using the + operator, str1 and str2 are concatenated to form "Hello World", which is then assigned to str3.

2. Concatenating Primitive Types to a String

The + operator can also concatenate primitive types (like integers, floats, etc.) with strings. Java automatically converts the primitive type to its string representation before concatenation. Here’s an example:

int num = 26;
String str1 = "Alphabets";
String str2 = num + str1; // Assigns "26Alphabets" to str2

In this example:

  • num is an integer with the value 26.

  • str1 is a string containing "Alphabets".

  • When num is concatenated with str1 using the + operator, num is converted to the string "26", and the result is "26Alphabets", which is assigned to str2.

3. Handling Null Values

If a reference variable contains null, the + operator treats it as the string "null". Here’s an example:

String str1 = "I am ";
String str2 = null;
String str3 = str1 + str2; // Assigns "I am null" to str3

In this example:

  • str1 contains "I am ".

  • str2 is null.

  • When str1 is concatenated with str2, str2 is treated as the string "null", resulting in "I am null", which is assigned to str3.

While the + operator is convenient for string concatenation, it is not the most efficient way to build large strings. This is because each concatenation creates a new string, which can be costly in terms of memory and performance. For more complex scenarios or when dealing with large amounts of data, consider using StringBuilder or StringBuffer.

Using StringBuilder

StringBuilder is a mutable sequence of characters. It is more efficient for concatenating strings in a loop or when you need to perform many concatenations.

StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" World");
String result = sb.toString(); // "Hello World"

Using StringBuffer

StringBuffer is similar to StringBuilder but is thread-safe, meaning it is synchronized and can be used safely in a multi-threaded environment.

StringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" World");
String result = sb.toString(); // "Hello World"
  • The + operator can concatenate strings and automatically convert and concatenate primitive types.

  • Null values are treated as the string "null" during concatenation.

  • For better performance in complex scenarios, use StringBuilder or StringBuffer.

3) Equality, Relational, and Conditional Operators

1. Equals and Not Equal Operators

The == (equals) and != (not equal) operators in Java are used to compare values. However, their behaviour differs significantly when dealing with primitive types versus reference types.

Primitive Types

For primitive types such as int, double, float, etc., the == operator checks if the values of the two operands are the same, and the != operator checks if the values are different.

Example:

int a = 5;
int b = 5;
boolean isEqual = (a == b); // isEqual is true
boolean isNotEqual = (a != b); // isNotEqual is false

In this example, isEqual is true because both a and b have the same value. Conversely, isNotEqual is false because a and b are not different.

Reference Types

For reference types (objects), the == operator checks if both references point to the same object in memory, not if the objects themselves are equivalent in content. This is often not the desired behaviour when comparing objects.

Example:

String str1 = new String("Hello");
String str2 = new String("Hello");
boolean isEqual = (str1 == str2); // isEqual is false
boolean isContentEqual = str1.equals(str2); // isContentEqual is true

In this example:

  • isEqual is false because str1 and str2 are two different objects in memory, even though they contain the same string.

  • isContentEqual is true because the equals method of the String class compares the content of the strings, not their memory addresses.

The equals Method

The equals method is intended to compare the contents of two objects to determine if they are logically equivalent. The default implementation of equals in java.lang.Object is similar to the == operator, meaning it checks for reference equality. However, many classes override this method to provide content-based equality.

Example:

StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = new StringBuilder("Hello");
boolean isEqual = (sb1 == sb2); // isEqual is false
boolean isContentEqual = sb1.equals(sb2); // isContentEqual is false

In this example:

  • isEqual is false because sb1 and sb2 are different objects in memory.

  • isContentEqual is also false because StringBuilder does not override the equals method, so it falls back to the default implementation, which checks for reference equality.

instanceof operator

The instanceof operator is used to compare an object to a specified type. It determines whether an object is an instance of a particular class, subclass, or any implemented interface. Here are some key points about the instanceof operator:

  • All Reference Variables are Instances of java.lang.Object: By default, all reference variables of all classes and interfaces are instances of the java.lang.Object class, which is the root class of the Java class hierarchy.

  • null is Not an Instance of Any Class or Interface: The instanceof operator will return false if the object being tested is null.

Example:

class SuperClass {}
class SubClass extends SuperClass {}

public class InstanceofTest {
    public static void main(String[] args) {
        SuperClass sup = new SuperClass();
        SuperClass sub = new SubClass();

        System.out.println("------------------SuperClass instanceof---");
        System.out.println("SuperClass instanceof SuperClass - " + (sup instanceof SuperClass));
        System.out.println("SuperClass instanceof SubClass - " + (sup instanceof SubClass));
        System.out.println("SuperClass instanceof java.lang.Object - " + (sup instanceof java.lang.Object));

        System.out.println("\n------------------SubClass instanceof---");
        System.out.println("SubClass instanceof SuperClass - " + (sub instanceof SuperClass));
        System.out.println("SubClass instanceof SubClass - " + (sub instanceof SubClass));
        System.out.println("SubClass instanceof java.lang.Object - " + (sub instanceof java.lang.Object));
    }
}

Output:

------------------SuperClass instanceof---
SuperClass instanceof SuperClass - true // This will print true because sup is an instance of SuperClass
SuperClass instanceof SubClass - false // This will print false because sup is not an instance of SubClass.
SuperClass instanceof java.lang.Object - true // This will print true because all classes in Java are subclasses of java.lang.Object.

------------------SubClass instanceof---
SubClass instanceof SuperClass - true // This will print true because sub is an instance of SubClass, which is a subclass of SuperClass.
SubClass instanceof SubClass - true // This will print true because sub is an instance of SubClass.
SubClass instanceof java.lang.Object - true   // This will print true because all classes in Java are subclasses of java.lang.Object.

2. Relational Operators

Relational operators are used to compare values and return boolean results.

  • They are binary operators (take two operands)

  • Always return true or false

  • Commonly used in control statements

OperatorDescriptionExample (a=5, b=10)Result
!=Not Equal to operatora!=btrue
>Greater thana>bfalse
<Less thana<btrue
>=Greater than or equal toa>=bfalse
<=Less than or equal toa<=btrue

Examples:

int a = 5;
int b = 10;
boolean result = a < b; // result is true

String str = "Hello";
boolean isString = str instanceof String; // isString is true
public class RelationalOperatorTest {
    public static void main(String[] args) {
        int x = 4;
        int y = 2;

        System.out.println(x > y); // true
        System.out.println(x >= y); // true
        System.out.println(x < y); // false
        System.out.println(x <= y); // false
        System.out.println(x >= 4); // true
        System.out.println(y <= 2); // true
    }
}

3. Conditional Operators

The conditional operator gives us an expression that has the effect of an if-else. The ternary operator (?:) allows you to choose between two values based on a condition.

  • ? :: Ternary (conditional) operator

Examples:

int a = 5;
int b = 10;
int max = (a > b) ? a : b; // max is 10
public class ConditionalOperatorTest {
    public static void main(String[] args) {
        int x = 4;
        int y = 2;

        System.out.println("---------  ?: -----------"); 
        System.out.println((x > 4) ? "x is > 4" : "x is < 4");
        System.out.println((x == 3) ? "x == 3" : "x != 3");
    }
}

4) The Bitwise & Bit Shift Operators

1. Bitwise Operators

Bitwise operators manipulate individual bits of integer types in Java.

  • Applied to long, int, short, char, and byte

  • Perform operations at the binary level

  • Useful for low-level programming and optimization

OperatorDescription
&Binary AND: Copies a bit if it exists in both operands.
Binary ORBinary OR Operator copies a bit if it exists in either operand.
^Binary XOR: Copies a bit if it is set in one operand but not both.
~Binary Ones Complement: Flips the bits of the operand.

Example Program:

public class BitWiseOperatorTest {
    public static void main(String[] args) {
        int x = 38; // 0010 0110
        int y = 58; // 0011 1010

        System.out.println(x + " - " + Integer.toBinaryString(x));
        System.out.println(y + " - " + Integer.toBinaryString(y));

        int z = x & y;
        System.out.println("\n& operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));

        z = x ^ y;
        System.out.println("\n^ operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));

        z = x | y;
        System.out.println("\n| operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));
    }
}

2. Bitshift Operators

Bitshift operators move bits to the left or right:

<<Binary Left Shift: Shifts the left operand's value left by the specified number of bits.
>>Binary Right Shift: Shifts the left operand's value right by the specified number of bits.
>>>Shift Right Zero Fill: Shifts the left operand's value right by the specified number of bits, filling shifted values with zeros.

Example Program:

public class BitShiftOperatorTest {
    public static void main(String[] args) {
        int x = 38; // 0010 0110

        System.out.println(x + " - " + Integer.toBinaryString(x));

        int z = x >> 2;
        System.out.println("\n>> operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));

        z = x << 2;
        System.out.println("\n<< operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));

        x = 38;
        z = x >>> 2;
        System.out.println("\n>>> operator");
        System.out.println(z + " - " + Integer.toBinaryString(z));
    }
}

5) Boolean Logical Operators

Boolean Logical Operators All Boolean logical operators can be used only with boolean operand(s). They are mostly used in control statements to compare two (or more) conditions.

OperatorDescription
!returns true if the operand is false, and false if the operand is true.
&&returns true if both operands are true. If either operand is false, it returns false.
&returns true if both operands are true. If either operand is false, it returns false.
logical ORreturns true if either operand is true. If both operands are false, it returns false.
bitwise ORreturns true if either operand is true. If both operands are false, it returns false.
^it returns true if one of the operands is true, but not both. If both operands are the same, it returns false.
&=if both operands evaluate to true, &= returns true. Otherwise, it returns false.
^=if both operands evaluate to different values, that is, one of the operands is true but not both, ^= returns true. Otherwise, it returns false.

Truth Table for Logical Operators

aba & b (AND)a OR b (OR)a ^ b (XOR)~a or !a (NOT)
true (1)true (1)truetruefalsefalse
true (1)false (0)falsetruetruefalse
false (0)true (1)falsetruetruetrue
false (0)false (0)falsefalsetruetrue

Let’s go through each operator:

  1. NOT Operator (~a or !a):

    • The NOT operator negates the value of its operand. If a is true, then ~a (or !a) is false, and vice versa.

    • For example, if a is true, then ~a is false.

  2. AND Operator (a & b):

    • The AND operator returns true only if both a and b are true; otherwise, it returns false.

    • For example, if both a and b are true, then a & b is true.

  3. OR Operator (a | b):

    • The OR operator returns true if either a or b (or both) are true; otherwise, it returns false.

    • For example, if either a or b (or both) are true, then a \| b is true.

  4. XOR Operator (a ^ b):

    • The XOR (exclusive OR) operator returns true if exactly one of a or b is true; otherwise, it returns false.

    • For example, if a is true and b is false (or vice versa), then a ^ b is true.

Example

public class BooleanLogicalOperatorsExample {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;

        // Using '&&' operator
        System.out.println("a && b: " + (a && b)); // Output: false

        // Using '||' operator
        System.out.println("a || b: " + (a || b)); // Output: true

        // Using '!' operator
        System.out.println("!a: " + (!a)); // Output: false

        // Using '^' operator
        System.out.println("a ^ b: " + (a ^ b)); // Output: true

        // Using '&' operator
        System.out.println("a & b: " + (a & b)); // Output: false

        // Using '|' operator
        System.out.println("a | b: " + (a | b)); // Output: true

        // Using '&=' operator
        a &= b;
        System.out.println("a &= b: " + a); // Output: false

        // Resetting a to true
        a = true;

        // Using '|=' operator
        a |= b;
        System.out.println("a |= b: " + a); // Output: true

        // Using '^=' operator
        a ^= b;
        System.out.println("a ^= b: " + a); // Output: true
    }
}

In this example, various Boolean logical operators are used to demonstrate their functionality. The output of each operation is printed to the console.

Short Circuit Evaluation

Short circuit evaluation is a feature in many programming languages, including Java, that optimizes the evaluation of logical expressions. It allows the program to stop evaluating an expression as soon as the result is determined. This can improve performance and prevent unnecessary operations.

Boolean Identities

There are two key Boolean identities that are fundamental to understanding short circuit evaluation:

  1. OR Operation (||):

    • true || anything will always produce true.

    • If the first operand is true, the overall expression will be true regardless of the second operand.

  2. AND Operation (&&):

    • false && anything will always produce false.

    • If the first operand is false, the overall expression will be false regardless of the second operand.

Logical Short Circuit Operators

In Java, the logical short circuit operators are:

  • Logical OR (||): If the first operand is true, the second operand is not evaluated.

  • Logical AND (&&): If the first operand is false, the second operand is not evaluated.

These operators are designed to stop evaluating as soon as the result is known, which can prevent unnecessary computations and potential side effects from the second operand.

Example

int a = 5;
int b = 10;
boolean result = (a > 0) && (b > 0); // result is true
boolean shortCircuit = (a < 0) && (b++ > 0); // shortCircuit is false
  1. First Expression: (a > 0) && (b > 0)

    • a > 0 evaluates to true because 5 > 0.

    • Since the first operand is true, the second operand (b > 0) is evaluated.

    • b > 0 evaluates to true because 10 > 0.

    • The overall expression is true && true, which results in true.

    • Therefore, result is true.

  2. Second Expression: (a < 0) && (b++ > 0)

    • a < 0 evaluates to false because 5 < 0 is false.

    • Since the first operand is false, the second operand (b++ > 0) is not evaluated.

    • The overall expression is false && anything, which results in false.

    • Therefore, shortCircuit is false.

    • Additionally, since the second operand is not evaluated, the increment operation b++ does not occur, and b remains 10.

Bitwise Operators

In contrast to the logical short circuit operators, the bitwise operators & and | always evaluate both operands:

  • Bitwise AND (&): Evaluates both operands and performs a bitwise AND operation.

  • Bitwise OR (|): Evaluates both operands and performs a bitwise OR operation.

These operators can be used with both Boolean and numeric values, but they do not short circuit.

Summary

  • Short Circuit Operators (&&, ||): Stop evaluating as soon as the result is known, preventing unnecessary operations and potential side effects.

  • Bitwise Operators (&, |): Always evaluate both operands, regardless of the result.

Conclusion

🔍 What are Operators? Operators are symbols that perform specific operations on one, two, or three operands, producing a result. They are the backbone of any programming language, and Java is no exception.

🔢 Types of Operators:

  1. Unary Operators: Operate on a single operand.

  2. Binary Operators: Operate on two operands.

  3. Ternary Operators: Operate on three operands.

🔧 Categories of Operators:

  • Assignment Operators: Assign values to variables.

  • Arithmetic Operators: Perform mathematical operations.

  • Relational Operators: Compare two values.

  • Logical Operators: Perform logical operations.

  • Bitwise Operators: Operate on individual bits.

  • Conditional Operators: Evaluate expressions based on conditions.

  • Type Comparison Operators: Compare types of objects.

💡 Key Concepts:

  • Expressions: Combinations of values, variables, operators, and function calls that produce a result.

  • L-values: Expressions that refer to a memory location and allow us to assign a value to it.

  • Side Effects: Occur when an expression modifies some state or value outside its local environment.

  • Operator Precedence: Determines the order in which operators are evaluated in expressions.

  • Operand Evaluation: Operands in Java are evaluated from left to right before applying the operation.

📊 Common Operators:

  • Arithmetic Operators: +, -, *, /, %

  • Equality Operators: ==, !=

  • Relational Operators: <, >, <=, >=

  • Logical Operators: &&, ||, !

  • Bitwise Operators: &, |, ^, ~, <<, >>, >>>

  • Conditional Operator: ?:

  • Type Comparison Operator: instanceof

🔍 Special Focus:

  • Remainder Operator (%): Different from modulus, especially with negative numbers.

  • Equals (==) and Not Equal (!=) Operators: Work well with primitives but be cautious with reference types.

🧠 Advanced Operators:

  • Bitwise & Bit Shift Operators: Manipulate individual bits of integer types.

  • Boolean Logical Operators: Used in control statements to compare conditions.

  • Short Circuit Evaluation: Optimizes the evaluation of logical expressions.

By understanding Java operators, we can write efficient and error-free code. By mastering these operators and their precedence, you can ensure that your expressions are evaluated in the order you intend, leading to correct and predictable results. The Java tutorial page lists down all the important topics you can go through to get a deeper understanding of the language basics and advanced concepts.

0
Subscribe to my newsletter

Read articles from Dilip Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dilip Patel
Dilip Patel

Software Developer