Java applications process data by evaluating expressions, which are combinations of literals, method calls, variable names, and operators. Evaluating an expression typically produces a new value, which can be stored in a variable, used to make a decision, and so on.
In this tutorial, you will learn how to write expressions for your Java programs. In many cases you'll use operators to write your Java expressions, and there are many types of operators to know how to use. I'll briefly introduce Java's operator types (including the additive, bitwise, logical, conditional, shift, and equality types) and their operands. You'll also learn about important concepts such as operator overloading and operator precedence, and you'll see a demonstration of primitive-type conversion. I'll conclude with a small Java program that you can use to practice primitive-type conversions on your own.
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 a 32-bit integer (int
); System.out.println("ABC");
is void (void
) because it returns no value; "Java"
is a string (String
); 98.6D
is a 64-bit double precision floating-point value (double
); and 89L
is a 64-bit long integer (long
). We don't know age
's type.
Experimenting with jshell
You can easily try out these and other simple expressions using jshell
. For example, enter 52
at the jshell>
prompt and you'll receive something like the following output:
$1 ==> 52
$1
is the name of a scratch variable that jshell
creates to store 52
. (Scratch variables are created whenever literals are entered.) Execute System.out.println($1)
and you'll see 52
as the output.
You can run jshell
with the -v
command-line argument (jshell -v
) to generate verbose feedback. In this case, entering 52
would result in the following message, revealing that scratch variable $1
has int
(32-bit integer) type:
| created scratch variable $1 : int
Next, try entering age
. In this case, you'll probably receive an error message that the symbol was not found. The Java Shell assumes that age
is a variable, but it doesn't know its type. You would have to include a type; for example, see what happens if you enter int age
.
Compound expressions
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 the number 10
. The order of evaluation (multiply first and then add) is dictated by Java's rule of precedence, which we'll get to shortly.
Operators and operands
Java's operators are classified by their number of operands:
- A unary operator has one operand, for example unary minus (e.g.,
-5
). - A binary operator has two operands, examples are multiplication and addition.
- A ternary operator has three operands; an example is the conditional operator (
?:
).
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 toage
's numeric value). - An infix operator is a binary or ternary operator between the operator's operands (e.g.,
age + 5
).
Another jshell example
I'll introduce more operators in the following sections, where I present examples in the form of applications. You could also try out these operators with jshell
, like so:
jshell> 6 + 2
$1 ==> 8
jshell> 7 * $1
$2 ==> 56
In this case, we first enter expression 6 + 2
, which jshell
evaluates, assigning the resulting 8 to scratch variable $1
. Next, we multiply $1
by 7
, which stores 56 in scratch variable $2
. This example demonstrates that you can use scratch variables in Java expressions.
Operator types in Java
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
operand1 + operand2
, where each operand must be of character or numeric type, addoperand2
tooperand1
and return the sum. Example:4 + 6
. - Subtraction: Given
operand1 - operand2
, where each operand must be of character or numeric type, subtractoperand2
fromoperand1
and return the difference. Example:4 - 6
. - Postdecrement: Given
variable--
, wherevariable
must be of character or numeric type, subtract 1 fromvariable
's value (storing the result invariable
) and return the original value. Example:x--;
. - Postincrement: Given
variable++
, wherevariable
must be of character or numeric type, add 1 tovariable
's value (storing the result invariable
) and return the original value. Example:x++;
. - Predecrement: Given
--variable
, wherevariable
must be of character or numeric type, subtract 1 from its value, store the result invariable
, and return the new decremented value. Example:--x;
. - Preincrement: Given
++variable
, wherevariable
must be of character or numeric type, add 1 to its value, store the result invariable
, and return the new incremented value. Example:++x;
. - String concatenation: Given
operand1 + operand2
, where at least one operand is ofString
type, appendoperand2
's string representation tooperand1
's string representation and return the result. Example:"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.
Example application: Additive operators
Listing 1 presents a small application for playing with Java's additive operators.
Listing 1. Additive operators in Java (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");
}
}
You learned in the previous tutorial how to use 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
Studying this output offers 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). Here's a formal definition:
Given
variable[index]
, whereindex
must be of integer (int
) type, read a value from or store a value intovariable
's storage element at locationindex
. Example: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
.
Example application: Array index operator
Listing 2 presents the source code to an example application that lets you play with the array index operator.
Listing 2. Array index operator in Java (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. Two items are of special 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. (Later in this tutorial I'll introduce type conversions, and you'll 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, meaning their types must agree. For example, you cannot assign a string literal to an integer variable. I'll explain more about this when we 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;
.