- Dividing a floating-point/double precision floating-point value by 0 causes the operator to return one of the following special values: +infinity (the dividend is positive), -infinity (the dividend is negative), or NaN -- Not a Number -- (the dividend and divisor are both 0).
- Dividing an integer value by integer 0 causes the operator to throw an
`ArithmeticException`

object. We'll explore exceptions in a future Java 101 article.

Compile Listing 7 (`javac MulOp.java`

) and run the application (`java MulOp`

). You should observe the following output:

```
192.0
21
1
Infinity
-Infinity
NaN
Exception in thread "main" java.lang.ArithmeticException: / by zero
at MulOp.main(MulOp.java:11)
```

## Object creation operator

The *object creation operator* (`new`

) is used to create an object from a class or to create an array. This operator is formally defined below:

- Given
`new`

, allocate memory for object and call constructor specified as*identifier*(*argument list*)

. Example:*identifier*(*argument list*)`new String("ABC")`

- Given
`new`

, allocate a one-dimensional array of values. Example:*identifier*[*integer size*]`new int[5]`

To create a two-dimensional array, the syntax changes to

(e.g.,*identifier*[*integer size*][*integer size*]`new double[5][5]`

). For additional dimensions, append an`[`

per dimension.*integer size*]

Object and array creation is a rich topic, so we'll dive into it another time.

## Relational operators

The *relational operators* impose an ordering on their operands by determining which operand is greater, lesser, and so on. These operators include greater than (`>`

), greater than or equal to (`>=`

), less than (`<`

), and less than or equal to (`<=`

). Type checking (`instanceof`

) is also considered to be relational. These operators are formally defined below:

- Greater than: Given

, where each operand must be of character or numeric type, return true when*operand1*>*operand2*is greater than`operand1`

. Otherwise, return false. Example:`operand2`

`65.3 > 22.5`

- Greater than or equal to: Given

, where each operand must be of character or numeric type, return true when*operand1*>=*operand2*is greater than or equal to`operand1`

. Otherwise, return false. Example:`operand2`

`0 >= 0`

- Less than: Given

, where each operand must be of character or numeric type, return true when*operand1*<*operand2*is less than`operand1`

. Otherwise, return false. Example:`operand2`

`x < 15`

- Less than or equal to: Given

, where each operand must be of character or numeric type, return true when*operand1*<=*operand2*is less than or equal to`operand1`

. Otherwise, return false. Example:`operand2`

`0 <= 0`

- Type checking: Given

, where*operand1*instanceof*operand2*is an object and`operand1`

is a class (or other user-defined type), return true when`operand2`

is an instance of`operand1`

. Otherwise, return false.`operand2`

Listing 8 presents the source code to a `RelOp`

application that lets you play with the relational operators.

#### Listing 8. RelOp.java

```
class RelOp
{
public static void main(String[] args)
{
int x = 10;
System.out.println(x > 10);
System.out.println(x >= 10);
System.out.println(x < 10);
System.out.println(x <= 10);
System.out.println("A" instanceof String);
}
}
```

Compile Listing 8 (`javac RelOp.java`

) and run the application (`java RelOp`

). You should observe the following output:

```
false
true
false
true
true
```

The final output line is interesting because it proves that a string literal (e.g., `"A"`

) is in fact a `String`

object.

## Shift operators

The *shift operators* let you shift an integral value left or right by a specific number of bit positions. These operators include left shift (`<<`

), signed right shift (`>>`

), and unsigned right shift (`>>>`

); and are formally defined below:

- Left shift: Given

, where each operand must be of character or integer type, shift*operand1*<<*operand2*'s binary representation left by the number of bits that`operand1`

specifies. For each shift, a 0 is shifted into the rightmost bit and the leftmost bit is discarded. Only the five low-order bits of`operand2`

are used when shifting a 32-bit integer (to prevent shifting more than the number of bits in a 32-bit integer). Only the six low-order bits of`operand2`

are used when shifting a 64-bit integer (to prevent shifting more than the number of bits in a 64-bit integer). The shift preserves negative values. Furthermore, it's equivalent to (but faster than) multiplying by a multiple of 2. Example:`operand2`

`3 << 2`

- Signed right shift: Given

, where each operand must be of character or integer type, shift*operand1*>>*operand2*'s binary representation right by the number of bits that`operand1`

specifies. For each shift, a copy of the sign bit (the leftmost bit) is shifted to the right and the rightmost bit is discarded. Only the five low-order bits of`operand2`

are used when shifting a 32-bit integer (to prevent shifting more than the number of bits in a 32-bit integer). Only the six low-order bits of`operand2`

are used when shifting a 64-bit integer (to prevent shifting more than the number of bits in a 64-bit integer). The shift preserves negative values. Furthermore, it's equivalent to (but faster than) dividing by a multiple of 2. Example:`operand2`

`-5 >> 2`

- Unsigned right shift: Given

, where each operand must be of character or integer type, shift*operand1*>>>*operand2*'s binary representation right by the number of bits that`operand1`

specifies. For each shift, a zero is shifted into the leftmost bit and the rightmost bit is discarded. Only the five low-order bits of`operand2`

are used when shifting a 32-bit integer (to prevent shifting more than the number of bits in a 32-bit integer). Only the six low-order bits of`operand2`

are used when shifting a 64-bit integer (to prevent shifting more than the number of bits in a 64-bit integer). The shift doesn't preserve negative values. Furthermore, it's equivalent to (but faster than) dividing by a multiple of 2. Example:`operand2`

`42 >>> 2`

Listing 9 presents the source code to a `ShiftOp`

application that lets you play with the shift operators.

#### Listing 9. ShiftOp.java

```
class ShiftOp
{
public static void main(String[] args)
{
System.out.println(1 << 8);
System.out.println(8 >> 2);
System.out.println(-1 >> 1);
System.out.println(-1 >>> 1);
}
}
```

Compile Listing 9 (`javac ShiftOp.java`

) and run the application (`java ShiftOp`

). You should observe the following output:

```
256
2
-1
2147483647
```

The output reveals that bit shifting is equivalent to multiplying or dividing by multiples of 2 (but is faster). The first output line is equivalent to the value derived from `2 * 2 * 2 * 2 * 2 * 2 * 2 * 2`

and the second output line is equivalent to the value derived from `8 / 4`

. The final two output lines show the difference between preserving and not preserving the sign bit where negative values are concerned.

## Unary minus/plus operators

The final operators that Java supports are *unary minus* (`-`

) and *unary plus* (`+`

). Unary minus returns the negative of its operand (e.g., `-8`

returns -8 and `--8`

returns 8), whereas unary plus returns its operand unchanged (e.g., `+8`

returns 8 and `+-8`

returns -8). Unary plus is not commonly used, but is included in Java's set of operators for completeness.

## Precedence and associativity

I previously mentioned that Java's rules of *precedence* (priority in order) dictate the order in which compound expressions are evaluated. For the common arithmetic operators (e.g., addition and multiplication), Java follows the established precedence conventions (e.g., multiplication first and then addition). For other operators, order of evaluation isn't as clear. For example, how does Java evaluate `6 > 3 * 2`

? Does the comparison precede multiplication or vice-versa?

The following list shows you the precedence of Java's operators. Operators closer to the top have higher precedence than operators lower down. In other words, operators higher up in the list are performed first. Operators that have the same precedence are listed on the same line. When the Java compiler encounters multiple operators with the same precedence in the same compound expression, it generates code to perform the operations according to their associativity:

- Array index, member access, method call, postdecrement, postincrement
- Bitwise complement, cast, logical complement, object creation, predecrement, preincrement, unary minus, unary plus
- Division, multiplication, remainder
- Addition, string concatenation, subtraction
- Left shift, signed right shift, unsigned right shift
- Greater than, greater than or equal to, less than, less than or equal to, type checking
- Equality, inequality
- Bitwise AND, logical AND
- Bitwise exclusive OR, logical exclusive OR
- Bitwise inclusive OR, logical inclusive OR
- Conditional AND
- Conditional OR
- Conditional
- Assignment, compound assignment

You won't always want to follow this order. For example, you might want to perform addition before multiplication. Java lets you violate precedence by placing subexpressions between round brackets (parentheses). A parenthesized subexpression is evaluated first. Parentheses can be nested, in which a parenthesized subexpression can be located within a parenthesized subexpression. In this case, the innermost parenthesized subexpression is evaluated first.

During evaluation, operators with the same precedence level (e.g., addition and subtraction) are processed according to their *associativity* (how operators having the same precedence are grouped when parentheses are absent). For example, `10 * 4 / 2`

is evaluated as if it was `(10 * 4) / 2`

because `*`

and `/`

are left-to-right associative operators. In contrast, `a = b = c = 50;`

is evaluated as if it was `a = (b = (c = 50));`

(`50`

is assigned to `c`

, `c`

's value is assigned to `b`

, and `b`

's value is assigned to `a`

-- all three variables contain 50) because `=`

is a right-to-left associative operator.

Most of Java's operators are left-to-right associative. Right-to-left associative operators include assignment, bitwise complement, cast, compound assignment, conditional, logical complement, object creation, predecrement, preincrement, unary minus, and unary plus.

I've created a small application for playing with precedence and associativity. Listing 10 presents its source code.

#### Listing 10. PA.java

```
class PA
{
public static void main(String[] args)
{
System.out.println(10 * 4 + 2);
System.out.println(10 * (4 + 2));
int a, b, c;
a = b = c = 50;
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
```

Compile Listing 10 (`javac PA.java`

) and run the application (`java PA`

). You should observe the following output:

```
42
60
50
50
50
```

In Listing 10, suppose I specified `(a = b) = c = 50;`

instead of `a = b = c = 50;`

because I want `a = b`

to be evaluated first. How would the compiler respond -- and why?

## Converting between types

My previous binary and ternary operator examples presented operands having the same type (e.g., each of `6 * 5`

's operands is an `int`

). In many cases, operands will not have the same type, and the Java compiler will need to generate bytecode that converts an operand from one type to another before generating bytecode that performs the operation. For example, when confronted by `5.1 + 8`

, the compiler generates bytecode to convert 32-bit integer `8`

to its double precision floating-point equivalent followed by bytecode to add these double precision values. (In the example, the compiler would generate an `i2d`

instruction to convert from `int`

to `double`

and then a `dadd`

instruction to add the two `double`

s.)

How does the compiler know which operand to convert? For primitive-type operands, its choice is based on the following widening rules, which essentially convert from a type with a narrower set of values to a type with a wider set of values:

- Convert byte integer to short integer, integer, long integer, floating-point, or double precision floating-point.
- Convert short integer to integer, long integer, floating-point, or double precision floating-point.
- Convert character to integer, long integer, floating-point, or double precision floating-point.
- Convert integer to long integer, floating-point, or double precision floating-point.
- Convert long integer to floating-point or double precision floating-point.
- Convert floating-point to double precision floating-point.

Regarding expression `5.1 + 8`

, we can see that the compiler chooses to convert `8`

to a `double`

based on the rule for converting an integer to double precision floating-point. If it converted `5.1`

to an `int`

, which is a narrower type, information would be lost because the fractional part would be effectively truncated. Therefore, the compiler always chooses to widen a type so information isn't lost.

These rules also help to explain why, in `BitwiseOp.java`

, the binary values resulting from expressions such as `System.out.println(~x);`

were 32 bits long instead of 16 bits long. The compiler converts the short integer in `x`

to a 32-bit integer value before performing bitwise complement, via `iconst_m1`

and `ixor`

instructions -- exclusive OR the 32-bit integer value with 32-bit integer -1 and produce a 32-bit integer result. The Java virtual machine provides no `sconst_m1`

and `sxor`

instructions for performing bitwise complement on short integers. Byte integers and short integers are always widened to 32-bit integers.

Earlier, I mentioned that you would discover why `'C' - 'A'`

in (`grades['C' - 'A']`

) produces an integer index. Character literals `'C'`

and `'A'`

are represented in memory by their Unicode values, which are unsigned 16-bit integers. When it encounters this expression, the Java compiler generates an `iconst_2`

instruction, which is `int`

value 2. In this case, no subtraction is performed because of optimization. However, if I replaced `'C' - 'A'`

with `'C' - base`

, where `base`

is a `char`

variable initialized to `'A'`

, the compiler would generate the following bytecode: