Operators

A computer program is a collection of operations that together achieve a certain function. There are many types of operations, including addition, subtraction, multiplication, division, and bit shifting. In this section you will learn various Java operations.

An operator performs an operation on one, two or three operands. Operands are the targets of an operation and the operator is a symbol representing the action. For example, here is an additive operation:

x + 4

In this case, x and 4 are the operands and + is the operator.

An operator may or may not return a result.

Note

Any legal combination of operators and operands are called an expression. For example, x + 4 is an expression. A boolean expression results in either true or false. An integer expression produces an integer. And, the result of a floating-point expression is a floating point number.

Operators that require only one operand are called unary operators. There are a few unary operators in Java. Binary operators, the most common type of Java operator, take two operands. There is also one ternary operator, the ? : operator, that requires three operands.

=    >    <    !    ~    ? :  instanceof
==   <=   >=   !=   &&   ||   ++   --
+    -    *    /    &    |    ^    %    <<    >>    >>>
+=   -=   *=   /=   &=   |=   ^=   %=   <<=   >>=   >>>=

Table 2.4: Java operators

In Java, there are six categories of operators.

  • Unary operators
  • Arithmetic operators
  • Relational and conditional operators
  • Shift and logical operators
  • Assignment operators
  • Other operators

Each of these operators is discussed in the following sections.

Unary Operators

Unary operators operate on one operand. There are six unary operators, all discussed in this section.

Unary Minus Operator –

The unary minus operator returns the negative of its operand. The operand must be a numeric primitive or a variable of a numeric primitive type. For example, in the following code, the value of y is -4.5;

float x = 4.5f;
float y = -x;

Unary Plus Operator +

This operator returns the value of its operand. The operand must be a numeric primitive or a variable of a numeric primitive type. For example, in the following code, the value of y is 4.5.

float x = 4.5f;
float y = +x;

This operator does not have much significance since its absence makes no difference.

Increment Operator ++

This operator increments the value of its operand by one. The operand must be a variable of a numeric primitive type. The operator can appear before or after the operand. If the operator appears before the operand, it is called the prefix increment operator. If it is written after the operand, it becomes the postfix increment operator.

As an example, here is a prefix increment operator in action:

int x = 4;
++x;

After ++x, the value of x is 5. The preceding code is the same as

int x = 4;
x++; 

After x++, the value of x is 5.

However, if the result of an increment operator is assigned to another variable in the same expression, there is a difference between the prefix operator and its postfix twin. Consider this example.

int x = 4;
int y = ++x;
// y = 5, x = 5

The prefix increment operator is applied before the assignment. x is incremented to 5, and then its value is copied to y.

However, check the use of the postfix increment operator here.

int x = 4;
int y = x++;
// y = 4, x = 5

With the postfix increment operator, the value of the operand (x) is incremented after the value of the operand is assigned to another variable (y).

Note that the increment operator is most often applied to ints. However, it also works with other types of numeric primitives, such as float and long.

Decrement Operator

This operator decrements the value of its operand by one. The operand must be a variable of a numeric primitive type. Like the increment operator, there are also the prefix decrement operator and the postfix decrement operator. For instance, the following code decrements x and assigns the value to y.

int x = 4;
int y = --x; 
// x = 3; y = 3

In the following example, the postfix decrement operator is used:

int x = 4;
int y = x--; 
// x = 3; y = 4

Logical Complement Operator !

This operator can only be applied to a boolean primitive or an instance of java.lang.Boolean. The value of this operator is true if the operand is false, and false if the operand is true. For example:

boolean x = false;
boolean y = !x;  
// at this point, y is true and x is false

Bitwise Complement Operator ~

The operand of this operator must be an integer primitive or a variable of an integer primitive type. The result is the bitwise complement of the operand. For example:

int j = 2;
int k = ~j; // k = -3; j = 2

To understand how this operator works, you need to convert the operand to a binary number and reverse all the bits. The binary form of 2 in an integer is:

0000 0000 0000 0000 0000 0000 0000 0010

Its bitwise complement is

1111 1111 1111 1111 1111 1111 1111 1101

which is the representation of -3 in an integer.

Arithmetic Operators

There are four types of arithmetic operations: addition, subtraction, multiplication, division, and modulus. Each arithmetic operator is discussed here.

Addition Operator +

The addition operator adds two operands. The types of the operands must be convertible to a numeric primitive. For example:

byte x = 3;
int y = x + 5; // y = 8

Make sure the variable that accepts the addition result has a big enough capacity. For example, in the following code the value of k is -294967296 and not 4 billion.

int j = 2000000000; // 2 billion
int k = j + j; // not enough capacity. A bug!!!

On the other hand, the following works as expected:

long j = 2000000000; // 2 billion
long k = j + j; // the value of k is 4 billion

Subtraction Operator –

This operator performs subtraction between two operands. The types of the operands must be convertible to a numeric primitive type. As an example:

int x = 2;
int y = x – 1;     // y = 1

Multiplication Operator *

This operator perform multiplication between two operands. The type of the operands must be convertible to a numeric primitive type. As an example:

int x = 4;
int y = x * 4;     // y = 16

Division Operator /

This operator perform division between two operands. The left hand operand is the dividend and the right hand operand the divisor. Both the dividend and the divisor must be of a type convertible to a numeric primitive type. As an example:

int x = 4;
int y = x / 2;     // y = 2

Note that at runtime a division operation raises an error if the divisor is zero.

The result of a division using the / operator is always an integer. If the divisor does not divide the dividends equally, the remainder will be ignored. For example

int x = 4;
int y = x / 3;     // y = 1

The java.lang.Math class, explained in Chapter 5, “Core Classes,” can perform more sophisticated division operations.

Modulus Operator %

The modulus operator perform division between two operands and returns the remainder. The left hand operand is the dividend and the right hand operand the divisor. Both the dividend and the divisor must be of a type that is convertible to a numeric primitive type. For example the result of the following operation is 2.

8 % 3

Equality Operators

There are two equality operators, == (equal to) and != (not equal to), both operating on two operands that can be integers, floating points, characters, or boolean. The outcome of equality operators is a boolean.

For example, the value of c is true after the comparison.

int a = 5;
int b = 5;
boolean c = a == b;

As another example,

boolean x = true;
boolean y = true;
boolean z = x != y;

The value of z is false after comparison because x is equal to y.

Relational Operators

There are five relational operators: <, >, <=, and >= and instanceof. The first four operators are explained in this section. instanceof is discussed in Chapter 7, “Inheritance.”

The <, >, <=, and >= operators operate on two operands whose types must be convertible to a numeric primitive type. Relational operations return a boolean.

The < operator evaluates if the value of the left-hand operand is less than the value of the right-hand operand. For example, the following operation returns false:

9 < 6

The > operator evaluates if the value of the left-hand operand is greater than the value of the right-hand operand. For example, this operation returns true:

9 > 6

The <= operator tests if the value of the left-hand operand is less than or equal to the value of the right-hand operand. For example, the following operation evaluates to false:

9 <= 6

The >= operator tests if the value of the left-hand operand is greater than or equal to the value of the right-hand operand. For example, this operation returns true:

9 >= 9

Conditional Operators

There are three conditional operators: the AND operator &&, the OR operator ||, and the ? : operator. Each of these is detailed below.

The && operator

This operator takes two expressions as operands and both expressions must return a value that must be convertible to boolean. It returns true if both operands evaluate to true. Otherwise, it returns false. If the left-hand operand evaluates to false, the right-hand operand will not be evaluated. For example, the following returns false.

(5 < 3) && (6 < 9)

The || Operator

This operator takes two expressions as operands and both expressions must return a value that must be convertible to boolean. || returns true if one of the operands evaluates to true. If the left-hand operand evaluates to true, the right-hand operand will not be evaluated. For instance, the following returns true.

(5 < 3) || (6 < 9)

The ? : Operator

This operator operates on three operands. The syntax is

expression1 ? expression2 : expression3

Here, expression1 must return a value convertible to boolean. If expression1 evaluates to true, expression2 is returned. Otherwise, expression3 is returned.

For example, the following expression returns 4.

(8 < 4) ? 2 : 4

Shift Operators

A shift operator takes two operands whose type must be convertible to an integer primitive. The left-hand operand is the value to be shifted, the right-hand operand indicates the shift distance. There are three types of shift operators:

  • the left shift operator <<
  • the right shift operator >>
  • the unsigned right shift operator >>>

The Left Shift Operator <<

The left shift operator bit-shifts a number to the left, padding the right bits with 0. The value of n << s is n left-shifted s bit positions. This is the same as multiplication by two to the power of s.

For example, left-shifting an int whose value is 1 with a shift distance of 3 (1 << 3) results in 8. Again, to figure this out, you convert the operand to a binary number.

0000 0000 0000 0000 0000 0000 0000 0001

Shifting to the left 3 shift units results in:

0000 0000 0000 0000 0000 0000 0000 1000

which is equivalent to 8 (the same as 1 * 23).

Another rule is this. If the left-hand operand is an int, only the first five bits of the shift distance will be used. In other words, the shift distance must be within the range 0 and 31. If you pass an number greater than 31, only the first five bits will be used. This is to say, if x is an int, x << 32 is the same as x << 0; x << 33 is the same as x << 1.

If the left-hand operand is a long, only the first six bits of the shift distance will be used. In other words, the shift distance actually used is within the range 0 and 63.

The Right Shift Operator >>

The right shift operator>> bit-shifts the left-hand operand to the right. The value of n >> s is n right-shifted s bit positions. The resulting value is n/2s.

As an example, 16 >> 1 is equal to 8. To prove this, write the binary representation of 16.

0000 0000 0000 0000 0000 0000 0001 0000

Then, shifting it to the right by 1 bit results in.

0000 0000 0000 0000 0000 0000 0000 1000

which is equal to 8.

The Unsigned Right Shift Operator >>>

The value of n >>> s depends on whether n is positive or negative. For a positive n, the value is the same as n >> s.

If n is negative, the value depends on the type of n. If n is an int, the value is (n>>s)+(2<<~s). If n is a long, the value is (n>>s)+(2L<<~s).

Assignment Operators

There are twelve assignment operators:

=  +=  -=  *=  /=  %=  <<=  >>=  >>>=  &=  ^=  |=

The left-hand operand must be a variable. For instance:

int x = 5;

Except for the assignment operator =, the rest work the same way and you should see each of them as consisting of two operators. For example, += is actually + and =. The assignment operator <<= has two operators, << and =.

The two-part assignment operators work by applying the first operator to both operands and then assign the result to the left-hand operand. For example x += 5 is the same as x = x + 5.

x -= 5 is the same as x = x – 5.

x <<= 5 is equivalent to x = x << 5.

x &= 5 produces the same result as x = x &= 5.

Integer Bitwise Operators & | ^

The bitwise operators& | ^ perform a bit to bit operation on two operands whose types must be convertible to int. & indicates an AND operation, | an OR operation, and ^ an exclusive OR operation. For example,

0xFFFF & 0x0000 = 0x0000
0xF0F0 & 0xFFFF = 0xF0F0
0xFFFF | 0x000F = 0xFFFF
0xFFF0 ^ 0x00FF = 0xFF0F

Logical Operators & | ^

The logical operators& | ^ perform a logical operation on two operands that are convertible to boolean. & indicates an AND operation, | an OR operation, and ^ an exclusive OR operation. For example,

true & true  = true
true & false = false
true | false = true
false | false = false
true ^ true = false
false ^ false = false
false ^ true = true

Operator Precedence

In most programs, multiple operators often appear in an expression, such as.

int a = 1;
int b = 2;
int c = 3;
int d = a + b * c;

What is the value of d after the code is executed? If you say 9, you’re wrong. It’s actually 7.

Multiplication operator * takes precedence over addition operator +. As a result, multiplication will be performed before addition. However, if you want the addition to be executed first, you can use parentheses.

int d = (a + b) * c;

The latter will assign 9 to d.

Table 2.5 lists all the operators in the order of precedence. Operators in the same column have equal precedence.

Operator

postfix operators

[ ] . (params) expr++ expr–

unary operators

++expr –expr +expr -expr ~ !

creation or cast

new (type)expr

multiplicative

* / %

additive

+ –

shift

<< >> >>>

relational

< > <= >= instanceof

equality

== !=

bitwise AND

&

bitwise exclusive OR

^

bitwise inclusive OR

|

logical AND

&&

logical OR

||

conditional

? :

assignment

= += -= *= /= %= &= ^= |= <<= >>= >>>=

Table 2.5: Operator precedence

Note that parentheses have the highest precedence. Parentheses can also make expressions clearer. For example, consider the following code:

int x = 5;
int y = 5;
boolean z = x * 5 == y + 20;

The value of z after comparison is true. However, the expression is far from clear.

You can rewrite the last line using parentheses.

boolean z = (x * 5) == (y + 20);

which does not change the result because * and + have higher precedence than ==, but this makes the expression much clearer.

Promotion

Some unary operators (such as +, , and ~) and binary operators (such as +, -, *, /) cause automatic promotion, i.e. elevation to a wider type such as from byte to int. Consider the following code:

byte x = 5;
byte y = -x; // error

The second line surprisingly causes an error even though a byte can accommodate -5. The reason for this is the unary operator – causes the result of -x to be promoted to int. To rectify the problem, either change y to int or perform an explicit narrowing conversion like this.

byte x = 5;
byte y = (byte) –x;

For unary operators, if the type of the operand is byte, short, or char, the outcome is promoted to int.

For binary operators, the promotion rules are as follows.

  • If any of the operands is of type byte or short, then both operands will be converted to int and the outcome will be an int.
  • If any of the operands is of type double, then the other operand is converted to double and the outcome will be a double.
  • If any of the operands is of type float, then the other operand is converted to float and the outcome will be a float.
  • If any of the operands is of type long, then the other operand is converted to long and the outcome will be a long.

For example, the following code causes a compile error:

short x = 200;
short y = 400;
short z = x + y;

You can fix this by changing z to int or perform an explicit narrowing conversion of x + y, such as

short z = (short) (x + y);

Note that the parentheses around x + y is required, otherwise only x would be converted to int and the result of addition of a short and an int will be an int.