You are currently viewing Java Operators
java_logo

Java Operators

  • Post author:
  • Post category:Operators
  • Post last modified:January 12, 2024


In Java, an operator is a symbol or a set of symbols that performs an operation on one or more operands. These operands can be variables, values, or literals, and they are the entities on which the operation is carried out. The operator, together with its operands, forms an expression that produces a result.

int x = 5;       // Variable as operand
int y = 3;       // Variable as operand

int result = x + y;  // Addition operator applied to variables

In this example, the addition operator (+) is applied to the variables x and y, producing a result stored in the variable result. The terms “operator,” “operand,” and “result” are fundamental in understanding how Java expressions operate, forming the foundation for concise and expressive coding.

1. Types of Operators

Java operators can be categorized into three types: unary, binary, and ternary.

  • Unary Operators: Operate on a single operand. Examples include the unary minus (-x) or the logical NOT (!flag).
  • Binary Operators: Work with two operands. Common binary operators include addition (x + y), subtraction (x - y), and multiplication (x * y).
  • Ternary Operator: Takes three operands. The most common ternary operator is the conditional operator (condition ? trueExpression : falseExpression), providing a concise way to express conditional statements.

Each operator type has a specific precedence, determining the order in which operations are executed within an expression.

2. Operator Precedence

In Java, operator precedence refers to the order in which operators are evaluated in an expression. Unlike simple left-to-right evaluation, certain operators have higher precedence and are evaluated first. This behavior can be likened to the rules of mathematics.

For example, the multiplication (*) operator has higher precedence than the addition (+) operator. Consider the following coding example:

int result = 5 + 3 * 2;

Here, due to operator precedence, the multiplication is performed first, resulting in 5 + (3 * 2), and the final result is 11.

Unless overridden by parentheses, Java operators generally follow the order of operations. If two operators have the same level of precedence, the left-to-right evaluation is applied.

Here’s a table summarizing the order of operator precedence in Java:

OperatorSymbols and examples
Post-unary operatorsexpression++, expression
Pre-unary operators++expression, expression
Other unary operators-, !, ~, +, (type)
Multiplications/division/modulus*, /, %
Addition/substraction+, –
Shift operators<<, >>, >>>
Relational operators<, >, <=, >=, instanceof
Equal to / not equal to==, !=
Logical operators&, ^, |
Short-circuit logical operators&&, ||
Ternary operatorsboolean expression ? expression1 : expression2
Assignment operators=, +=, -=, *=, /=, %=, ^=, |=, <<=, >>=, >>>=

3. Unary Operators

These operators require exactly one operand and are employed to carry out various operations, from incrementing and decrementing values to changing the sign of a numerical expression.

Java supports several unary operators, each serving a unique purpose. Let’s break down the most commonly used ones along with their descriptions:

OperatorDescriptionExample
++Increment the value of the operand by 1int x = 5; ++x;
Decrement the value of the operand by 1int y = 10; --y;
+Positive sign (explicit, rarely used)int a = -7; +a;
Negation or change the sign of the operandint b = 3; -b;
!Logical NOT (negates the boolean value of the operand)boolean flag = true; !flag;
(type)Type casting (converts one data type to another)double d = (double) 5;

3.1. Increment and decrement operators

Increment (++) and decrement (--) operators are essential tools in Java for manipulating numerical values. These unary operators have a high order of precedence, often being applied before binary operators, and they come in two flavors: pre-increment/post-increment and pre-decrement/post-decrement.

3.1.1. Pre-Increment and Post-Increment:

Pre-Increment (++variable):

In pre-increment, the value of the variable is increased by 1 before its value is used in an expression.

int x = 5;
int result = ++x; // pre-increment
System.out.println(result); // Output: 6
System.out.println(x);      // Output: 6

In this example, x is incremented by 1 before being assigned to result. Both result and x end up with the value 6.

Post-Increment (variable++):

In post-increment, the current value of the variable is used in an expression before being increased by 1.

int y = 10;
int result = y++; // post-increment
System.out.println(result); // Output: 10
System.out.println(y);      // Output: 11

Here, result gets the original value of y (10), and then y is incremented by 1.

Pre-Decrement and Post-Decrement:

The principles of pre-decrement (--variable) and post-decrement (variable--) are analogous to their increment counterparts.

int a = 8;
int result = --a; // pre-decrement
System.out.println(result); // Output: 7
System.out.println(a);      // Output: 7

int b = 15;
int result = b--; // post-decrement
System.out.println(result); // Output: 15
System.out.println(b);      // Output: 14
Combining Pre-Increment and Post-Increment:
int count = 3;
int result = ++count + count++;
System.out.println(result); // Output: 8
System.out.println(count);  // Output: 5

In this example, both pre-increment and post-increment operators are used together. The pre-increment increases the value of count by 1 before being added to the post-incremented value of count. The final value of count is 5, and the result is 8.

3.2. Logical Complement Operator and Negation Operators

The logical complement operator is a unary operator that operates on a single boolean operand. Its primary purpose is to negate or invert the value of the boolean expression it precedes.

boolean isJavaCool = true;
boolean notCool = !isJavaCool;

System.out.println(notCool); // Output: false

In this example, the ! operator flips the value of isJavaCool from true to false. The logical complement is particularly useful in conditions and decision-making, where you want to consider the opposite of a given boolean state.

While the logical complement operator handles boolean values, the negation operator (-) takes center stage when dealing with numeric expressions. This unary operator reverses the sign of a numeric value, turning positive numbers into negatives and vice versa:

int positiveNumber = 7;
int negativeNumber = -positiveNumber;

System.out.println(negativeNumber); // Output: -7

Here, the negation operator transforms the value of positiveNumber from 7 to -7.

The power of the negation operator becomes evident when applied multiple times, especially when enclosed within parentheses. Let’s examine an example:

int number = 10;
int doubleNegation = -(-number);

System.out.println(doubleNegation); // Output: 10

In this scenario, the net effect is that the original value is preserved despite the negations.

Attempting to use the logical complement operator with a numeric expression or the negation operator with a boolean expression results in a compilation error.

// Logical complement applied to a boolean
boolean flag = true;
// The following line won't compile
// boolean result = -flag;

// Negation applied to a numeric expression
int numericValue = 85;
// The following line won't compile
// int negatedValue = !numericValue;

4. Binary Operators

In the world of Java programming, binary operators are the workhorses that perform a myriad of tasks, from mathematical operations to logical expressions and variable assignments. These operators take two operands and combine them to produce a new value.

OperatorDescriptionExample
+Additionint sum = 5 + 3;
Subtractionint difference = 7 - 4;
*Multiplicationint product = 2 * 6;
/Divisiondouble quotient = 10 / 2;
%Modulus (remainder)int remainder = 11 % 3;

4.1. Arithmetic Operators

Arithmetic operators in Java, including addition (+), subtraction (-), multiplication (*), division (/), and modulus (%), are fundamental tools for numerical computations. The modulus operator, represented by the symbol % in Java, is a mathematical operator that calculates the remainder when one integer is divided by another. In other words, it returns the amount left over after the division of two integers.

int sum = 5 + 3; // sum is 8
int difference = 7 - 4; // difference is 3
int product = 2 * 6; // product is 12
double quotient = 10 / 2; // quotient is 5.0
int remainder = 11 % 3; // remainder is 2

Understanding operator precedence is crucial when expressions involve multiple operators. The default precedence follows the order: multiplication and division have higher precedence than addition and subtraction. To override default precedence, parentheses can be used to explicitly indicate the desired order of operations:

int result = 5 + 3 * 2; // result is 11 (multiplication has higher precedence)
int newResult = (5 + 3) * 2; // modifiedResult is 16 (addition is performed first)

Numeric Promotion

Each primitive numeric type has a bit-length. A long takes up more space than an int, which in turn takes up more space than a short,… Let’s start by explaining the rules for numeric promotion:

  1. Smaller to Larger:
    • Smaller data types are automatically promoted to larger data types during arithmetic operations.
    • The order of promotion is: byteshortintlongfloatdouble.
  2. Integer Promotion:
    • If an expression involves int, byte, or short, the result is promoted to int even if neither of the operands is of type int.
  3. Floating-Point Promotion:
    • If an expression involves float and int operands, the int is promoted to float.
    • If an expression involves double and float operands, the float is promoted to double.
  4. Mixed-Type Arithmetic:
    • If an expression involves operands of different types, the smaller type is promoted to the larger type.
    • If one operand is of type double, the other is promoted to double.
  5. Constants and Literals:
    • Numeric literals, such as 5 or 10.5, have a default type (e.g., int or double).
    • Constants without a specified type are treated as int, but they can be promoted.

examples:

    int intValue = 5;
    long longValue = 10L;
    var result = intValue + longValue; // int is promoted to long
    System.out.println(((Object) result).getClass()); //class java.lang.Long

    double doubleValue = 10.5;
    var result2 = intValue * doubleValue; // int is promoted to double
    System.out.println(((Object) result2).getClass()); // class java.lang.Double

    byte byteValue = 3;
    short shortValue = 7;
    var result3 = byteValue + shortValue; // Both bytes are promoted to int
    System.out.println(((Object) result3).getClass());; // class java.lang.Integer

4.2. Assignment Operators and Casting Values

OperatorDescriptionExample
=Assigns the value on the right to the left operandint x = 10;

When working with variables in Java, the assignment operator (=) plays a fundamental role in assigning values to variables. Understanding how the compiler handles numeric promotion is crucial, especially when casting is required for compatibility between different data types.

basics:

At its core, the assignment operator is used to assign the value on the right side of the equation to the variable on the left side. Let’s dive into a simple example:

int x = 10; // Assigning the value 10 to the variable x

numeric promotion:

Numeric promotion refers to the automatic conversion of “smaller” data types to “larger” ones during expressions. Java will automatically promote from smaller to larger data types to avoid loss of precision. Consider the following example:

int intValue = 5;
double doubleValue = 10.5;

double result = intValue + doubleValue;

In this example, intValue is automatically promoted to a double before the addition operation. This promotion allows the result to be a double without losing precision.

Casting values:

Casting is the explicit interpretation of one data type as another. It becomes crucial when converting between data types of different sizes.

  • Widening, or implicit casting, occurs when converting to a larger data type. This is done automatically by the compiler, and no explicit casting is required.
  • Narrowing, or explicit casting, is necessary when converting to a smaller data type. It involves placing the data type in parentheses before the value. Be cautious, as this may result in loss of precision.
int intValue = 50;
long longValue = intValue; // Implicit casting to a larger data type
long longValue = (long) intValue; // same as previous example, cast is optional

double doubleValue = 123.456;
int intValue = (int) doubleValue; // Explicit casting to a smaller data type
int intValue = doubleValue; // Compiler error without casting

Now, let’s consider an example where we multiply two short values and attempt to assign the result directly to a short. As we mentioned, Java automatically promotes the result of such operations to int. To overcome this, we’ll use explicit casting to assign the result to a short.

public class ShortMultiplicationExample {
    public static void main(String[] args) {
        short shortValue1 = 5;
        short shortValue2 = 3;

        // short result = shortValue1 * shortValue2; // Compilation error

        // Using explicit casting to assign the result to a short
        short result = (short) (shortValue1 * shortValue2);
    }
}


In the given example, we have two short variables, shortValue1 and shortValue2. When attempting to multiply these two short values and directly assign the result to another short, a compilation error occurs due to automatic promotion to int. To resolve this issue, explicit casting is employed. The multiplication result, enclosed in parentheses, is explicitly cast to short. Subsequently, the result, now of type short, is displayed.

4.3. Compound Assignment Operators

OperatorDescriptionExample
=Assigns the value on the right to the left operandint x = 10;
+=Adds the right operand to the left operandx += 5; // equivalent to x = x + 5;
-=Subtracts the right operand from the left operandx -= 3; // equivalent to x = x - 3;
*=Multiplies the left operand by the right operandx *= 2; // equivalent to x = x * 2;
/=Divides the left operand by the right operandx /= 4; // equivalent to x = x / 4;
%=Computes the remainder of the divisionx %= 3; // equivalent to x = x % 3;


Compound assignment operators in Java are a shorthand notation for combining an assignment with a built-in arithmetic or logical operation. These operators provide a concise way to perform an operation on a variable and update its value in a single step.

int x = 5;
x += 3; // Equivalent to x = x + 3;
System.out.println("Result: " + x); // Output: Result: 8

double y = 10.0;
y /= 2; // Equivalent to y = y / 2;
System.out.println("Result: " + y); // Output: Result: 5.0

Compound operators are useful for more than just shorthand. They can save us from having to explicitly cast values. Here’s an example:

short shortValue = 5;
shortValue += 3; // the result is implicitly cast to short

long longValue = 10;
int intValue = 5;
intValue = intValue * longValue; // compilation Error
intValue = (int) (intValue * longValue); // compiles because of explicit cast
intValue *= longValue; // compiles because of implicit cast

4.4. Comparing values

Determining equality in Java can be nuanced, especially when dealing with different data types and object comparisons. Let’s explore the equality operators, their application on primitives and objects, and provide examples of scenarios where equality checks can be tricky.

4.4.1. Equality operators

OperatorApplied to primitivesApplied to objects
==Returns true if two values represent the same valueReturns true if the two values reference the same object
!=Returns true if two values represent different valuesReturns true if the two values do not reference the same object
4.4.1.1. Comparing Numeric or Character Primitive Types

When comparing two numeric or character primitive types, the equality operators can be used straightforwardly. If the numeric values are of different data types, Java will automatically promote them.

int num1 = 5;
double num2 = 5.0;

System.out.println(num1 == num2); // true (automatic promotion of int to double)
4.4.1.2. Comparing Boolean Values

Boolean values can be compared directly using the equality operators.

boolean bool1 = true;
boolean bool2 = false;

System.out.println(bool1 == bool2); // false
4.4.1.2. Comparing Objects (including null)

When comparing objects, the == operator compares the memory addresses (references) of the objects. This is crucial to understand because it checks whether the two references point to the same object, not whether the objects have the same content.

String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = str1;

System.out.println(str1 == str2); //false (same content, but different objects)
System.out.println(str1 == str3); //true (the references point to the same object)
System.out.println(null == null); // true 
4.4.1.2. Pitfalls: Attempting to mix and match the types

Attempting to compare different types, without explicit casting will result in a compilation error.

int num = 5;
boolean someValue = false;
String word = "Hello";

// This will not compile
 System.out.println(num == someValue); // cannot compare int to boolean
 System.out.println(num == word); // cannot compare int to String

4.4.2. Relational Operators

Relational operators in Java are used to compare values and determine relationships between them.

OperatorDescription
<Returns true if the value on the left is less than the value on the right
<=Returns true if the value on the left is less than or equal to the value on the right
>Returns true if the value on the left is greater than the value on the right
>=Returns true if the value on the left is greater than or equal to the value on the right
instanceofReturns true if the object on the left is an instance of the specified class on the right
4.4.2.1. Numeric Comparison Operators

When using the numeric comparison operators (>, <, >=, <=), if the two numeric operands are not of the same data type, the smaller one is promoted. This automatic promotion ensures that the comparison is done with compatible types.

int intValue = 5;
double doubleValue = 5.0;

System.out.println(intValue >= doubleValue); /* true (automatic promotion of int to double) */
4.4.2.2. ‘instanceof’ Operator

The instanceof operator is useful for determining whether an arbitrary object is an instance of a particular class at runtime. It’s often employed in scenarios involving polymorphism.

public class TimeProcessor {
    public static int processTime(Number time) {
        if (time instanceof Integer) {
            int intValue = (Integer) time;
            return intValue;
        } else {
            System.out.println("The type is not an Integer.");
            return time.intValue();
        }
    }

    public static void main(String[] args) {
        Number timeInteger = 42;
        Number timeDouble = 24.5;

        System.out.println(processTime(timeInteger)); // Output: 42
        System.out.println(processTime(timeDouble));   /* Output: The type is not an Integer. */
    }
}

In this example, the processTime method takes a Number type, and at runtime, it checks if it is an instance of Integer. If true, it casts it to int, and if false, it prints a message and returns the integer value of the time.

Attempting to use instanceof with incompatible types, like comparing a String with Integer, will result in a compilation error.

String text = "Hello, World!";

// This is invalid and will not compile
 System.out.println(text instanceof Integer);

The instanceof operator in Java can be used to check if an object is an instance of a particular class, but it behaves differently when used with null. When null is used with instanceof, it always returns false.

public class InstanceOfExample {
    public static void main(String[] args) {
        String text = null;

        // Using instanceof with null
        if (text instanceof String) {
            System.out.println("text is an instance of String.");
        } else {
            System.out.println("text is not an instance of String.");
        }
    }
}

In this example, text is assigned the value null, and when the instanceof operator is used to check if it’s an instance of String, the output will be “text is not an instance of String.”

4.4.3. Logical Operators

Logical operators are indispensable tools for creating sophisticated conditional expressions in Java. Understanding how these operators work and incorporating them into your code can significantly enhance the expressiveness and logic of your programs. Whether combining conditions with && and || or negating values with !, logical operators are powerful elements of Java programming that contribute to writing more flexible and dynamic code.

OperatorDescription
&Logical AND is true only if both values are true
|Inclusive OR is true if at least one of the values is true
^Eclusive XOR is true only if one value is true and the other is false

The truth tables for these operators look like this:

ABA & B
falsefalsefalse
falsetruefalse
truefalsefalse
truetruetrue
ABA | B
falsefalsefalse
falsetruetrue
truefalsetrue
truetruetrue
ABA ^ B
falsefalsefalse
falsetruetrue
truefalsetrue
truetruefalse
public class LogicalAndExample {
    public static void main(String[] args) {
        boolean x = true;
        boolean y = false;

        boolean result = x & y;

        System.out.println("x & y: " + result); // Output: x & y: false
    }
}

public class LogicalOrExample {
    public static void main(String[] args) {
        boolean x = true;
        boolean y = false;

        boolean result = x | y;

        System.out.println("x | y: " + result); // Output: x | y: true
    }
}

public class LogicalXorExample {
    public static void main(String[] args) {
        boolean x = true;
        boolean y = false;

        boolean result = x ^ y;

        System.out.println("x ^ y: " + result); // Output: x ^ y: true
    }
}

Short-circuit operators:

the short-circuit logical operators are && (logical AND) and || (logical OR). These operators exhibit short-circuiting behavior, meaning they evaluate the second operand only if necessary. This behavior can be useful for optimizing code and preventing unnecessary evaluations.

OperatorDescriptionShort-Circuiting Behavior
&&Short-circuit AND – Returns true if both operands are trueSkips evaluation of the right operand if the left is false
||Short-circuit OR – Returns true if at least one operand is true; otherwise, returns false.If the left side is true, then the right side will not be evaluated
public class ShortCircuitAndExample {
    public static void main(String[] args) {
        int x = 5;
        boolean y = false;

        if (x < 0 && computeResult()) {
            System.out.println("Condition is true.");
        } else {
            System.out.println("Condition is false.");
        }
    }

    private static boolean computeResult() {
        System.out.println("Computing result...");
        return true;
    }
}

In this example, the computeResult() method is not called because the left operand (x < 0) is false.

Using short-circuit operators is not only efficient but also provides a way to handle certain conditions more gracefully, particularly when dealing with potential null values.

public class AvoidNullPointerExceptionExample {
    public static void main(String[] args) {
        String text = null;

        if (text != null && text.length() > 0) {
            System.out.println("Length is greater than 0.");
        } else {
            System.out.println("Length is 0 or text is null.");
        }
    }
}

In this example, the short-circuit AND (&&) prevents the evaluation of text.length() if text is null, thus avoiding a potential null pointer exception.

5. Ternary Operator

The ternary operator in Java, represented by ? :, is a unique operator that takes three operands. It provides a concise way to express a conditional statement in a single line. The syntax of the ternary operator is:

booleanExpression ? expression1 : expression2

The ternary operator is essentially a condensed form of an if-else statement. The above expression can be equivalent to the following if-else statement:

if (booleanExpression) {
    result = expression1;
} else {
    result = expression2;
}

example:

public class TernaryOperatorExample {
    public static void main(String[] args) {
        int x = 5;
        int y = 10;

        // Using the ternary operator to find the maximum
        int max = (x > y) ? x : y;

        System.out.println("Maximum value: " + max);  // Output: Maximum value: 10
    }
}

In this example, the ternary operator is used to find the maximum value between x and y. If x is greater than y, it assigns the value of x to max; otherwise, it assigns the value of y.

public class TernaryOperatorStringExample {
    public static void main(String[] args) {
        int score = 85;

        // Using the ternary operator to determine the result string
        String result = (score >= 70) ? "Pass" : "Fail";

        System.out.println("Result: " + result);  // Output: Result: Pass
    }
}

Here, the ternary operator is employed to determine the result string based on the value of the score. If the score is greater than or equal to 70, it assigns “Pass” to the result; otherwise, it assigns “Fail”.