In a programming language, operators are specific symbols that are used to perform operations on other programming language components to produce a result. The component(s) that the operator performs the operation on is (are) called operand(s). For example, in the statement
2 + 3
“+” is the operator, 2 and 3 are operands.
Java language defines a number of operators that can be categorized into the following categories:
- Equality and Relational Operators
- Arithmetic Operators
- Conditional Operators
- Logical Operators
- Unary operators
- Assignment operators
- Bitwise operators
- instanceof operator
Let’s see what these operator types are and how they work.
Equality and Relational Operators
These operators generate a boolean result, true or false and they operate on two operands. The equality and relational operators are:
Operator symbol | Operator name | Description | Applies To |
== | equal to | Returns true if left operand is the same as the right operand;otherwise returns false | used with every type of reference and object variables |
> | greater than | Returns true if left operand is greater than the right operand;otherwise returns false | used with number type primitives and their object types |
>= | greater than or equal to | Returns true if left operand is greater than or equal to the right operand;otherwise returns false | used with number type primitives and their object types |
< | less than | Returns true if left operand is less than the right operand;otherwise returns false | used with number type primitives and their object types |
<= | less than or equal to | Returns true if left operand is less than or equal to the right operand;otherwise returns false | used with number type primitives and their object types |
!= | not equal to | Returns true if left operand and the right operand are not the same; otherwise returns false | used with every type of reference and object variables |
Let’s see how these operators works in an example.
Public class MyClass {
public static void main() {
int x = 2;
System.out.println(“x = “ x);
System.out.println(“x == 2 : “ + (x == 2));
System.out.println(“x == 3 : “ + (x == 2));
System.out.println(“x > 3 : “ + (x > 3));
System.out.println(“x < 3 : “ + (x < 3));
System.out.println(“x >= 3 : “ + (x >= 3));
System.out.println(“x != 3 : “ + (x != 3));
}
}
The output would be
x : 2
x == 2: true
x == 3 : false
x > 3 : false
x < 3 : true
x >= 3 : false
2 != 3 : true
Arithmetic operators
Arithmetic operators operate on two numbers and generate numeric results. One exception to this is that the addition operator (+) also applies to Strings and is used in string concatenation.
Operator symbol | Operator name | Description |
+ | Addition | Adds left and right operands |
– | Subtraction | Subtracts right operand from left operand |
* | Multiplication | Multiplies left and right operands |
/ | Division | Divides the left operand by right operand |
% | Modulus | Divides the left operand by right and returns the remainder (does not apply to floating point numbers) |
Logical Operators
Logical operators generate true or false results and they operate on two booleans with the exception of logical NOT operator which operates on a single operand.
Operator Symbol | Operator Name | Description |
& | Logical AND | true & true → returns true
true & false → returns false false & true → returns false false & false → returns false |
| | Logical OR | true | true → returns true
true | false → returns true false | true → returns true false | false → returns false |
&& | Short circuit logical AND | Uses the same logic as logical AND to determine the result. Looks at the left operand first. If it is false, returns false. Checks the right operand only if it is the left operand is true. |
|| | Short circuit logical OR | Uses the same logic as logical OR to determine the result. Looks at the left operand first. If it is true, returns true. Checks the right operand only if the left operand is false. |
^ | Logical exclusive OR (XOR) | When the left and right operands are different, returns true, otherwise returns false.
true ^ true → returns false true ^ false → returns true false ^ true → returns true false ^ false → returns false |
! | Logical NOT (boolean invert) | Returns the inverse of the operand it operates on.
!false → returns true !true → returns false |
Let’s see how logical operators work in an example.
public class MyClass {
public static void main(String [] args) {
int x = 2;
System.out.println(“x = “ + x);
System.out.println(“(x == 2) & (x > 3) : ” + (x == 2) & (x > 3));
System.out.println(“(x == 2) && (x > 1) : ” + (x == 2) && (x > 1));
System.out.println(“(x > 3) | (x < 1) : ” + (x == 2) | (x > 3));
System.out.println(“(x == 2) || (x < 1) : ” + (x == 2) || (x < 1));
System.out.println(“(x == 2) ^ (x < 1) : ” + (x == 2) ^ (x < 1));
System.out.println(“!(x < 1) : ” + !(x < 1) );
}
}
The output would be:
x = 2
(x == 2) & (x > 3) : false
(x == 2) && (x > 1) : true
(x > 3) | (x < 1) : false
(x == 2) || (x < 1) : true
(x == 2) ^ (x < 1) : true
!(x < 1) : true
Conditional Operator
The conditional operator applies on three operands (ternary operator) and returns the second or the third operand. It is typically used to assign a value to a variable based on the value of the first operand. The format for the conditional operator is as follows:
<operand 1> ? <operand 2> : <operand 3>
This expression is translated as: If operand 1 evaluates to true return operand 2, otherwise return operand 3.
The first operand is of type boolean; typically it is an expression that evaluates to a boolean. If the evaluated value from operand 1 is true, second operand is returned as the result. If it is false, the third operand is returned as the result.
Let’s see how the conditional operator works in an example.
public class MyClass {
public static void main(String [] args) {
int x = 2;
int y = (x == 2) ? 3 : 5;
System.out.println(“(x == 2) ? 3 : 5 returns ” + y);
}
}
The output would be
(x == 2) ? 3 : 5 returns 3.
Here, in this example, y takes the value 3 because x == 2 evaluates to true.
Unary Operators
Unary operators operate on one operand. They apply to only numeric types.
Operator Symbol | Operator Name | Description |
+ | Unary + | Indicates a positive value for a number. It is not used, as positive numbers are already positive and it has no effect on negative numbers. |
– | Unary – | Negates the value of the number it operates on. |
++ | increment | Increments the value of the number by 1. |
— | decrement | Decrements the value of the number by 1. |
The ! operator that we saw before is also a unary operator.
Let’s see unary operators in an example.
public class MyClass {
public static void main(String [] args) {
int x = 2;
System.out.println(“x : “ + x);
System.out.println(“Applying ++ …“);
x++;
System.out.println(“x : “ + x);
System.out.println(“Applying — …“);
x–;
System.out.println(“x : “ + x);
System.out.println(“Applying – …“);
System.out.println(“x : “ + x);
}
}
The output would be
x : 2
Applying ++ …
x : 3
Applying – …
x : 2
Applying – …
x : -2
When we use ++ and – operators in a statement, it’s important if they they precede or succeed the operand. If they precede, they are applied on the operand before the statement is executed. If they succeed the operand, the statement gets executed and then the ++ or – operation is performed. For example;
int i = 0;
System.out.println(“The value of is “ + ++i));
generates the output
The value of i is 1
However, if we change the place of the ++ operator as follows
int i = 0;
System.out.println(“The value of is “ + i++));
the output would be
The value of i is 0
Assignment operator
The assignment operator, =, is used to assign values to variables. It is used both with primitive types and object types.
Assigning a value to a primitive;
int x = 2;
Assigning a value to an object;
MyObject myObject = new MyObject();
Bitwise Operators
Java also defines bitwise operators that are used to apply to change or shift the bits of a variable. Bitwise operators are used only with integeral numeric types, which are int, short, long, char and byte.
Here we need to talk a little bit about how Java stores bits of integral types in memory. In Java programming language, integral types are stored in JVM using a representation called two’s complement. In two’s complement representation, positive integrals are represented with their base 2 representations. The bit representations of negative numbers are found with the assumption that the sum of a positive number and its negative is 0.
In Java, the leftmost bit (also called the most significant bit or the sign bit) of an integral type represents the sign of the number. If it is 0, the value is positive, otherwise it is negative. Based on that, the bit representation of a positive number is base 2 representation of the number with all the remaining bits to the left padded with 0s. For example, bitwise representation of a byte with value 4:
00000100
Using two’s complement representation, the bitwise representation for the negative of a positive number is found as follows.
1- Find the bit representation of the positive number.
2- Invert all the bits.
3- Add one bit.
For example, if we want to find the bit representation of -4, first we invert all the bits in the bit representation of 4, the result becoming 11111011. Then we add 1 bit, getting the resulting bit representation as 11111100. So the bit representation of -4 is 11111100.
While getting the value for a bit representation that has 1 for the most significant bit, the following algorithm is followed.
1- Invert all the bits.
2- Add 1 bit.
3- Find the base 10 number corresponding to the base 64 representation and multiply the number by -1.
Let’s say we want to find what byte number the bitwise representation 11111100 corresponds to. Inverting all the bits gives us 00000011. Adding 1 bit to this number gives us 00000100. The byte value for this representation is 4. Multiplying 4 by -1 gives us -4.
Two’s complement representation is very important in understanding how bitwise and bit shift operations work in Java. We will use two byte numbers 10 and 20 as operands in bitwise and bit shift operations. A byte is 8 bits in Java, with the most significant bit reserved for the sign. So, a bit can have values between -127 and 128. The bitwise representation of 10 is 1010 (or showing all the bits, 00001010) and bitwise representation of 20 is 10100 (or, showing all the bits, 00010100). Let’s see how we apply the bitwise operators and shift operators with these numbers as operands.
Operator Symbol | Operator Name | Description Example | |
& | Bitwise AND | Applies the AND operation to two bits.
1 & 1 → returns 1 1 & 0 → returns 0 0 & 1 → returns 0 0 & 0 → returns 0 |
01010
10100 & ————– 00000 10 & 20 = 0 |
| | Bitwise OR | Applies the OR operation to two bits.
1 | 1 → returns 1 1 | 0 → returns 1 0 | 1 → returns 1 0 | 0 → returns 0 |
01010
10100 | ————- 11110 10 | 20 = 30. |
~ | Bitwise complement | Changes all the bytes in the number to their compliments. Compliment of 1 is 0 and compliment of 0 is 1. For example, if the bit representation of a number is 10, applying the 2’s compliment operator would change it to 01. This operation changes the sign of the number as it changes the value of the bit representing the sign. | Applying this to 10,
~1010 = 11110101 ~10 = -11. |
^ | Bitwise XOR | Applies XOR operator to two bits. Evaluates to 1 if the two bit operands are different, to 0 if they are the same. | 01010
10100 ^ ————- 11110 |
<< | Left shift | Shifts the bits of the left operand to the left by the number of bits set for the right operand and fills the open bits on the right with 0. Equivalent to multiplying the left operand by 2 e (the number specified by right operand). | Left shift 1010 by 2 bits, that gives us 101000. The value for this is 40. That is basically equivalent to multiplying 10 by 2e2. |
>> | Right shift | Shifts the bits of the left operand to the right by the number of bits set for the right operand. The bits on the right that fall out of the number after the shift are dropped. This operation is equivalent to dividing the left operand by 2 e (right operand). | Right shift 1010 by 2 bits gives us 10, which 2. The rightmost 2 bits, 10, are dropped. This is equivalent to getting the integral value for 10 / 2e2. |
>>> | Zero fill shift right | Same as right right operator but fills the shifted bits with zeros. | Right shift 1010 by 2 bits gives us 10, which 2. The rightmost 2 bits, 10, are dropped. This is equivalent to getting the integral value for 10 / 2e2. |
instanceof operator
The instanceof operator is a binary operator that is used to find out if a class is an instance of a specific class (or an instance of one of the subclasses of a class) or not. It operates only on classes and takes two operands. The operand on the left is an object variable; the one on the right is the name of a class. The result evaluates to true if the left operand is an instance of the right operand, otherwise it evaluates to false.
The instanceof operator is performed as follows.
<object reference> instanceof <classname>
The keyword instanceof is all lowercase. There should be at least one space on each side of the operator between the operator and the operands.
To see how instanceof operator is used, let’s define a String variable s.
String s = “Hello”;
Using instanceof operator with s and String returns true.
s instanceof String → returns true
If in this statement, String is replaced by any other object other than Object, the result would be false. String is a subclass of Object and any instance of String is an instance of Object, too. If the left operand is an instance of one of the subclasses of the left operand, the result would still be true.
s instanceof Integer → returns false
s instanceof Object → returns true