Operators
In Java, operators are symbols like +
, -
, /
, etc. that perform operations between two values and are fundamental to any programming language.
Without operators, we wouldn't be able to compare values, perform arithmetic
operations, or even assign values to variables.
This is done by the usage of symbols to effect operands
.
What are Operands?
In programming terms, operands are the values or variables that operators can perform operations on.
Take the expression 5 + 3
for instance, 5
and 3
are the operands and the +
symbol is the operator in this scenario.
Types of Operators
Java supports many types of operators, all with different use cases. For instance, consider a simple task of checking if a value is equal to 1 and then reacting to that in code by running an action. This would use both control-flow and a relational operator like so.
int someNumber = 1;
if (someNumber == 1) // == <-- Relational operator.
{
DoSomething();
}
Let's go over all the different types of operators in more detail.
Arithmetic
Arithmetic operators are used to perform basic mathematical operations on two operands, mainly numerical types. In Java, there are five arithmetic operators:
+
Addition- Adds the two operands together.
-
Subtraction- Subtracts the right operand from the left one.
*
Multiplication- Multiplies the two operands together.
/
Division- Divides the left operand by the right one.
%
Modulus- Returns the remainder of a division operation.
int a = 10;
int b = 5;
int addition = a + b; // Result: 15
int subtraction = a - b; // Result: 5
int multiplication = a * b; // Result: 50
int division = a / b; // Result: 2
int modulus = a % b; // Result: 0
// You can also perform operations directly with values as-well
int addValue = a + 20; // Result: 30
Relational
Relational operators are used to compare two operands. In Java, there are six relational operators:
==
Equal to- Checks if the two operands are equal.
!=
Not equal to- Checks if the two operands are not equal.
>
Greater than- Checks if the left operand is greater than the right one.
<
Less than- Checks if the left operand is less than the right one.
>=
Greater than or equal to- Checks if the left operand is greater than or equal to the right one.
<=
Less than or equal to- Checks if the left operand is less than or equal to the right one.
int a = 10;
int b = 5;
boolean bIsEqual = a == b; // Result: false
boolean bIsNotEqual = a != b; // Result: true
boolean bIsGreaterThan = a > b; // Result: true
boolean bIsLessThan = a < b; // Result: false
boolean bIsGreaterThanOrEqual = a >= b; // Result: true
boolean bIsLessThanOrEqual = a <= b; // Result: false
// You can also perform operations directly with values as-well
boolean bIsEqualValue = a == 10; // Result: true
These are mainly used in control-flow structures such as if
statements, while
, and for
loops, where they help determine the
path that the code should take based on certain conditions. We will discuss this in more detail in the control-flow page.
Logical
Logical operators are used to perform logical operations, typically within conditional statements. In Java, there are three primary logical operators:
&&
AND- Returns true if both operands are true.
||
OR- Returns true if at least one of the operands is true.
!
NOT- Returns the inverse of the operand. If the operand is true, it returns false, and vice versa.
boolean bTrue = true;
boolean bFalse = false;
boolean bAnd = bTrue && bFalse; // Result: false
boolean bOr = bTrue || bFalse; // Result: true
boolean bNot = !bTrue; // Result: false
Much like the relational operators these are also used typically in control-flow structures to determine paths code should take based on these conditions.
Assignment
Assignment operators are used to assign values to variables of a given data type. In Java, there are several assignment operators:
=
Assignment- Assigns the value from the right operand to the left operand.
+=
Add and assign- Adds the right operand to the left operand and assigns the result to the left operand.
-=
Subtract and assign- Subtracts the right operand from the left operand and assigns the result to the left operand.
*=
Multiply and assign- Multiplies the right operand by the left operand and assigns the result to the left operand.
/=
Divide and assign- Divides the left operand by the right operand and assigns the result to the left operand.
%=
Modulus and assign- Takes the modulus of the left operand by the right operand and assigns the result to the left operand.
int a = 10;
int b = 5;
a += b; // a = a + b, Result: 15
a -= b; // a = a - b, Result: 10
a *= b; // a = a * b, Result: 50
a /= b; // a = a / b, Result: 10
a %= b; // a = a % b, Result: 0
// You can also perform operations directly with values as-well
a += 20; // a = a + 20, Result: 20
Unary
Unary operators are used to perform operations on a single operand. In Java, there are five primary unary operators:
-
Unary minus- Negates an expression.
++
Increment- Increases the value of a variable by 1.
--
Decrement- Decreases the value of a variable by 1.
!
NOT- Returns the inverse of the operand. If the operand is true, it returns false, and vice versa.
~
Bitwise Complement- Inverts all bits in the operand.
Some of these are duplicates from other operator types because they are also classed as unary operators.
int a = 10;
int unaryMinus = -a; // Result: -10
a++; // a = a + 1, Result: 11
a--; // a = a - 1, Result: 10
boolean bTrue = true;
boolean bNot = !bTrue; // Result: false
int someNumber = 60; // 60 = 0011 1100
int bitwiseComplement = ~someNumber;
// someNumber -> 0011 1100
// Result: -61 = 1100 0011
Bitwise
Bitwise operators are used to perform operations on individual bits of integer data types. In Java, there are six bitwise operators:
These are the hardest operators to grasp and I would suggest they are more towards advanced Java usage, so don't worry about fully grasping these early on.
&
AND- Performs a Boolean AND operation on each bit of its integer arguments.
|
OR- Performs a Boolean OR operation on each bit of its integer arguments.
^
XOR- Performs a Boolean exclusive OR operation (meaning only 1 of two arguments can be true) on each bit of its integer arguments.
~
Complement- Unary operator that inverts all bits in the operand.
<<
Left shift- Shifts the bits of the number to the left and fills 0 on voids left as a result. The leftmost bits are discarded.
>>
Right shift- Shifts the bits of the number to the right and fills 0 on voids left as a result. The rightmost bits are discarded.
int a = 60; // 60 = 0011 1100
int b = 13; // 13 = 0000 1101
int and = a & b;
// a -> 0011 1100
// b -> 0000 1101
// Result: 12 = 0000 1100
int or = a | b;
// a -> 0011 1100
// b -> 0000 1101
// Result: 61 = 0011 1101
int xOr = a ^ b;
// a -> 0011 1100
// b -> 0000 1101
// Result: 49 = 0011 0001
int complement = ~a;
// a -> 0011 1100
// Result: -61 = 1100 0011
int leftShift = a << 2;
// a -> 0011 1100
// Result: 240 = 1111 0000 - All bits have been shifted 2 places to the left
int rightShift = a >> 2;
// a -> 0011 1100
// Result: 15 = 0000 1111 - All bits have been shifted 2 places to the right
Conditional
The conditional operator, also known as the ternary operator, is a shorthand for an if-else
statement and is the only operator in Java that works on three operands.
The operator is represented as ? :
- It starts with a boolean expression (the condition).
- If the condition is true, it returns the value before the
:
(the if part). - If the condition is false, it returns the value after the
:
(the else part).
int a = 10;
int b = 5;
int someResult = (a < b) ? a : b; // Result: 5
// If a is less than b, set SomeResult to a, otherwise; set someResult to b
Operator Precedence
Operator precedence determines the order that operations are performed when an expression involves multiple operators. Operators with higher precedence are evaluated before operators with lower precedence. Operators with the same precedence are evaluated from left-right, except for assignment operators, which are evaluated from right-left.
As this is a very well discussed topic and I have nothing to offer much more than a carbon copy from other resources, here is an article explaining operator precedence in more detail:
Casting
Casting in Java allows a variable of one type to be converted into another type. It's a way of telling the compiler, "Treat this piece of data as if it were of this other type". This can be useful when you want to perform operations between different types of data.
Implicit Casting
This type of casting happens automatically when we assign a smaller type to a larger type size, this process is called a widening conversion.
For example, assigning an int
to a long
or a float
to a double
using an assignment operator.
Referring back to the data types page, we know an int
is 32-bits
stored using 4-bytes
and a long
is 64-bits
stored using 8-bytes
so it is possible to use implicit casting when setting a long
variable to the value of an int
. But the other way round would
result in an error due to that being a narrowing conversion, and requiring explicit casting.
int smallNumber = 100;
long largeNumber = someNumber; // Implicit casting
long largeNumber = 210005100000L;
int smallNumber = largeNumber; // Error: Invalid Implicit casting
Explicit Casting
This type of casting needs to be done manually by placing the type we want to "cast" to in parentheses in front of the variable or value we are tying to convert,
this is also known as a narrowing conversion. For example, assigning a long
to an int
or a double
to a float
using an assignment operator.
Going back to what was mentioned as implicit casting, explicit casting is used when converting a data type of larger size to one with a smaller size.
long largeNumber = 210005100000L;
int smallNumber = (int)largeNumber; // Explicit casting - Results in data loss
In this case the smaller number being an int
cannot hold the long value being cast to an integer value, so it results in data loss.
The value of the smallNumber
variable ends up being -448297504
. This is because the int
data type in Java has a maximum value of 2147483647
,
and any value beyond this range results in an overflow. That overflow causes the integer to wrap around and start from its minimum value of -2147483648
.
The value of -448297504
is down to the way binary numbers handle overflow.