Java applications process data by evaluating *expressions*, which are combinations of literals, method calls, variable names, and operators. Expression evaluation typically produces a new value, which can be stored in a variable, used to make a decision, and so on. In this article, I'll show you how to create expressions for your programs. Many expressions involve operators, including additive, array-index, bitwise, conditional, and equality types. I'll introduce each operator and its operands, and also discuss important concepts such as operator overloading and operator precedence. We'll conclude with a primer on operator type conversion, including a small program that you can use to practice type conversions on your own. Note that examples in this article are based on Java 8.

## Evaluating simple expressions

A *simple expression* is a literal, variable name, or method call. No operators are involved. Here are some examples of simple expressions:

```
52 // integer literal
age // variable name
System.out.println("ABC"); // method call
"Java" // string literal
98.6D // double precision floating-point literal
89L // long integer literal
```

A simple expression has a type, which is either a primitive type or a reference type. In these examples, `52`

is an integer (`int`

), `System.out.println("ABC");`

is void (`void`

) because it returns no value, `"Java"`

is a string (`String`

), `98.6D`

is a double precision floating-point value (`double`

), and `89L`

is a long integer (`long`

). We don't know `age`

's type.

## Evaluating compound expressions with operators

A *compound expression* consists of one or more simple expressions integrated into a larger expression via an *operator*, which is a sequence of instructions symbolically represented in source code. The operator transforms its expression *operand(s)* into another value. For example, in `6 * 5`

, the multiplication operator (`*`

) transforms operands `6`

and `5`

into 30.

Compound expressions can be combined into larger expressions. For example, `6 * 5 + 10`

presents compound expression `6 * 5`

and a compound expression consisting of their product, addition operator `+`

, and `10`

. The order of their evaluation (multiply first and then add) is dictated by Java's **rules of precedence**, which we'll get to shortly.

Java's operators are classified by their number of operands. Operators with one operand (e.g., unary minus [`-`

], as in `-5`

) are *unary operators*. Operators with two operands (e.g., multiplication and addition) are *binary operators*. Finally, operators with three operands (e.g., conditional [`?:`

]) are *ternary operators*.

Java's operators are also classified by position. A *prefix operator* is a unary operator that precedes its operand (e.g., `-5`

), a *postfix operator* is a unary operator that follows its operand (e.g., `age++;`

-- add 1 to `age`

's numeric value), and an *infix operator* is a binary or ternary operator between the operator's operands (e.g., `age + 5`

).

Java provides many operators, which I discuss in the following sections.

## Additive operators

The *additive operators* increase or decrease a numeric value through addition and subtraction. Additive operators include addition (`+`

), subtraction (`-`

), postdecrement (`--`

), postincrement (`++`

), predecrement (`--`

), and preincrement (`++`

). String concatenation (`+`

) is also considered to be additive. Here's a formal definition for each of these operators:

- Addition: Given

, where each operand must be of character or numeric type, add*operand1*+*operand2*to`operand2`

and return the sum. Example:`operand1`

`4 + 6`

- Subtraction: Given

, where each operand must be of character or numeric type, subtract*operand1*-*operand2*from`operand2`

and return the difference. Example:`operand1`

`4 - 6`

- Postdecrement: Given

, where*variable*--must be of character or numeric type, subtract 1 from`variable`

's value (storing the result in`variable`

) and return the original value. Example:`variable`

`x--;`

- Postincrement: Given

, where*variable*++must be of character or numeric type, add 1 to`variable`

's value (storing the result in`variable`

) and return the original value. Example:`variable`

`x++;`

- Predecrement: Given
`--`

, where*variable*must be of character or numeric type, subtract 1 from its value, store the result in`variable`

, and return the new decremented value. Example:`variable`

`--x;`

- Preincrement: Given
`++`

, where*variable*must be of character or numeric type, add 1 to its value, store the result in`variable`

, and return the new incremented value. Example:`variable`

`++x;`

- String concatenation: Given

, where at least one operand is of*operand1*+*operand2*`String`

type, append's string representation to`operand2`

's string representation and return the result. Example:`operand1`

`"A" + "B"`

The addition, subtraction, postdecrement, postincrement, predecrement, and preincrement operators can generate values that overflow the limits of the result type. For example, adding two large positive 64-bit integer values can produce a value that cannot be represented in 64 bits. The resulting overflow is not detected or reported by Java's additive operators.

I've created a small application for playing with Java's additive operators. Listing 1 presents its source code.

#### Listing 1. AddOp.java

```
class AddOp
{
public static void main(String[] args)
{
System.out.println(125 + 463);
System.out.println(2.0 - 6.3);
int age = 65;
System.out.println(age);
System.out.println(age--);
System.out.println(age++);
System.out.println(--age);
System.out.println(++age);
System.out.println("A" + "B");
}
}
```

In the previous article, we used the JDK's `javac`

tool to compile Java source code and the `java`

tool to run the resulting application. Execute the following command to compile Listing 1:

`javac AddOp.java`

Assuming successful compilation, you should observe an `AddOp.class`

file in the current directory. Execute the following command to run it:

`java AddOp`

`AddOp`

responds by producing the following output:

```
588
-4.3
65
65
64
64
65
AB
```

The output provides insight into the postincrement, postdecrement, preincrement, and predecrement operators. For postincrement/postdecrement, `age`

's current value is output before the increment/decrement operation. For preincrement/predecrement, the operation is performed and its result is stored in `age`

, and then `age`

's new value is output.

## Array index operator

The *array index operator* (`[]`

) accesses an array element by providing the element's *index* (position). This operator is placed after the array variable's name, as in `grades[0]`

(access the first element in the array assigned to `grades`

; the first element is stored at index 0). This operator is formally defined below:

- Given

, where*variable*[*index*]must be of integer (`index`

`int`

) type, read a value from or store a value into's storage element at location`variable`

. Example:`index`

`temperatures[1]`

The value passed to * index* is a 32-bit integer that is either 0 or a positive value ranging to one less than the array's length, which is indicated by appending

`.length`

to the name of the array. For example, `grades.length`

returns the number of elements in the array assigned to `grades`

.Listing 2 presents the source code to an `ArrayIndexOp`

application that lets you play with the array index operator.

#### Listing 2. ArrayIndexOp.java

```
class ArrayIndexOp
{
public static void main(String[] args)
{
int[] grades = { 89, 90, 68, 73, 79 };
System.out.println(grades[1]);
grades[1] = 91;
System.out.println(grades[1]);
int index = 4;
System.out.println(grades[index]);
System.out.println(grades['C' - 'A']);
// System.out.println(grades[1D]);
}
}
```

Listing 2 is somewhat more interesting than Listing 1. After creating a five-element, one-dimensional array of integers (via an array initializer) and assigning the array's reference to `grades`

, `main()`

proceeds to access various elements. There are two items of interest:

- The array index operator's index must ultimately be a 32-bit integer (0 or a positive value). You can specify the name of an integer variable (e.g.,
`index`

), which contains the index value, as the index. - You can specify a calculation involving character literals. When I discuss type conversions later in this article, you will discover why
`'C' - 'A'`

produces an integer (2), which serves as a valid index.

The final example, which passes `1D`

as an index to the array index operator, is commented out because it will not compile. If you uncomment the line and attempt to compile Listing 2, you will receive an error message about incompatible types: "possible lossy conversion from `double`

to `int.`

"

Compile Listing 2 (`javac ArrayIndexOp.java`

) and run the application (`java ArrayIndexOp`

). You should observe the following output:

```
90
91
79
68
```

## Assignment operators

The *assignment operator* (`=`

) assigns an expression's value to a variable (e.g., `i = 6;`

), including an array element (e.g., `x[0] = 15;`

). The expression and variable must be assignment compatible: their types must agree. For example, you cannot assign a string literal to an integer variable. I'll have more to say about this topic when I discuss type conversions.

The compound assignment operators (`+=`

, `-=`

, `*=`

, `/=`

, `%=`

, `&=`

, `|=`

, `^=`

, `<<=`

, `>>=`

, `>>>=`

) evaluate expressions and assign the results to variables in one step. Each expression and variable must be assignment compatible. Each operator serves as a useful shortcut. For example, instead of specifying `x = x + 3;`

, you can specify the shorter and equivalent `x += 3;`

.

## Bitwise operators

The *bitwise operators* modify the binary values of their operands, which must be of an integer (`byte`

, `short`

, `int`

, or `long`

) or character type. These operators include bitwise AND (`&`

), bitwise complement (`~`

), bitwise exclusive OR (`^`

), and bitwise inclusive OR (`|`

); and are formally defined below:

- Bitwise AND: Given

, where each operand must be of character or an integer type, bitwise AND their corresponding bits and return the result. A result bit is set to 1 when each operand's corresponding bit is 1. Otherwise, the result bit is set to 0. Example:*operand1*&*operand2*`1 & 0`

- Bitwise complement: Given
`~`

, where*operand*must be of character or an integer type, flip`operand`

's bits (1s to 0s and 0s to 1s) and return the result. Example:`operand`

`~1`

- Bitwise exclusive OR: Given

, where each operand must be of character or an integer type, bitwise exclusive OR their corresponding bits and return the result. A result bit is set to 1 when one operand's corresponding bit is 1 and the other operand's corresponding bit is 0. Otherwise, the result bit is set to 0. Example:*operand1*^*operand2*`1 ^ 0`

- Bitwise inclusive OR: Given
*operand1*|*operand2*, which must be of character or an integer type, bitwise inclusive OR their corresponding bits and return the result. A result bit is set to 1 when either (or both) of the operands' corresponding bits is 1. Otherwise, the result bit is set to 0. Example:`1 | 0`

Listing 3 presents the source code to a `BitwiseOp`

application that lets you play with the bitwise operators.