Java Operators
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:
Number of Operands:
Unary Operators: Operate on a single operand.
Binary Operators: Operate on two operands.
Ternary Operators: Operate on three operands.
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.
Operator | Description |
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) |
new | Instance creation operator |
instanceof | Type 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 typeint
."Hello"
is a literal expression of typeString
.3.14
is a literal expression of typedouble
.
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
is5
.Type: The data type of the result. For example, the type of
2 + 3
isint
.
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
Expressions with Operations
2 + 3 * 4
This expression combines multiple operations.
Arithmetic Expression:
int result = 2 + 3; // result is 5
Here,
2 + 3
is an arithmetic expression that evaluates to5
.Relational Expression:
boolean isGreater = 5 > 3; // isGreater is true
Here,
5 > 3
is a relational expression that evaluates totrue
.Logical Expression:
boolean isTrue = (5 > 3) && (2 < 4); // isTrue is true
Here,
(5 > 3) && (2 < 4)
is a logical expression that evaluates totrue
.Method Call Expression:
int length = "Hello".length(); // length is 5
Here,
"Hello".length()
is a method call expression that evaluates to5
.
Properties of Expressions
Value | Result of the expression |
Type | Data type of the result (e.g., int, float) |
Storage | No storage allocated |
Expression Example: 2 + 3
Value | Type | Can assign to it? |
5 | int | No |
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
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. Sincex
has a storage location, it is an L-value, and we can assign a new value to it.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 arrayarr
. This element has a storage location, soarr[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.
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.Results of Arithmetic Operations:
int result = 2 + 3; (2 + 3) = 5; // Error: '2 + 3' is not an L-value
The expression
2 + 3
evaluates to5
, 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
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 variablex
to 3. This is a side effect because it modifies the state ofx
.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 ofi
by 1 before the value is used in the expression. The side effect is the modification ofi
from 5 to 6.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 ofi
by 1 after the value is used in the expression. The side effect is the modification ofi
from 5 to 6, butj
is assigned the original value ofi
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 (=
).
Precedence | Operator |
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:
Operator | Description |
+ | 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:
Operator | Description |
+ | 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
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.
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
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 of7
(positive).
Example 2:
-a % b
a = 7
b = -3
Calculation:
-7 % -3
Division:
-7 / -3
results in2
(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:
The remainder operator
%
in Java returns the remainder of the division of two numbers.The sign of the result is determined by the sign of the left-hand operand (dividend).
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
andstr2
are concatenated to form "Hello World", which is then assigned tostr3
.
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 withstr1
using the+
operator,num
is converted to the string "26", and the result is "26Alphabets", which is assigned tostr2
.
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
isnull
.When
str1
is concatenated withstr2
,str2
is treated as the string "null", resulting in "I am null", which is assigned tostr3
.
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
orStringBuffer
.
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
isfalse
becausestr1
andstr2
are two different objects in memory, even though they contain the same string.isContentEqual
istrue
because theequals
method of theString
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
isfalse
becausesb1
andsb2
are different objects in memory.isContentEqual
is alsofalse
becauseStringBuilder
does not override theequals
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 thejava.lang.Object
class, which is the root class of the Java class hierarchy.null
is Not an Instance of Any Class or Interface: Theinstanceof
operator will returnfalse
if the object being tested isnull
.
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
Operator | Description | Example (a=5, b=10) | Result |
!= | Not Equal to operator | a!=b | true |
> | Greater than | a>b | false |
< | Less than | a<b | true |
>= | Greater than or equal to | a>=b | false |
<= | Less than or equal to | a<=b | true |
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
Operator | Description |
& | Binary AND: Copies a bit if it exists in both operands. |
Binary OR | Binary 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.
Operator | Description |
! | 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 OR | returns true if either operand is true. If both operands are false, it returns false. |
bitwise OR | returns 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
a | b | a & b (AND) | a OR b (OR) | a ^ b (XOR) | ~a or !a (NOT) |
true (1) | true (1) | true | true | false | false |
true (1) | false (0) | false | true | true | false |
false (0) | true (1) | false | true | true | true |
false (0) | false (0) | false | false | true | true |
Let’s go through each operator:
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.
AND Operator (a & b):
The AND operator returns true only if both
a
andb
are true; otherwise, it returns false.For example, if both
a
andb
are true, thena & b
is true.
OR Operator (a | b):
The OR operator returns true if either
a
orb
(or both) are true; otherwise, it returns false.For example, if either
a
orb
(or both) are true, thena \| b
is true.
XOR Operator (a ^ b):
The XOR (exclusive OR) operator returns true if exactly one of
a
orb
is true; otherwise, it returns false.For example, if
a
is true andb
is false (or vice versa), thena ^ 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:
OR Operation (
||
):true || anything
will always producetrue
.If the first operand is
true
, the overall expression will betrue
regardless of the second operand.
AND Operation (
&&
):false && anything
will always producefalse
.If the first operand is
false
, the overall expression will befalse
regardless of the second operand.
Logical Short Circuit Operators
In Java, the logical short circuit operators are:
Logical OR (
||
): If the first operand istrue
, the second operand is not evaluated.Logical AND (
&&
): If the first operand isfalse
, 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
First Expression:
(a > 0) && (b > 0)
a > 0
evaluates totrue
because5 > 0
.Since the first operand is
true
, the second operand(b > 0)
is evaluated.b > 0
evaluates totrue
because10 > 0
.The overall expression is
true && true
, which results intrue
.Therefore,
result
istrue
.
Second Expression:
(a < 0) && (b++ > 0)
a < 0
evaluates tofalse
because5 < 0
isfalse
.Since the first operand is
false
, the second operand(b++ > 0)
is not evaluated.The overall expression is
false && anything
, which results infalse
.Therefore,
shortCircuit
isfalse
.Additionally, since the second operand is not evaluated, the increment operation
b++
does not occur, andb
remains10
.
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:
Unary Operators: Operate on a single operand.
Binary Operators: Operate on two operands.
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.
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