Java Language Basics

Java 101: Evaluate Java expressions with operators

A complete guide to the Java operator types and writing Java expressions in Java 12

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.

Note that the Java programming examples in this tutorial are based on Java 12.

download
Download the source code for Java programming examples used in this tutorial. Created by Jeff Friesen for JavaWorld.

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 to age'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, add operand2 to operand1 and return the sum. Example: 4 + 6.
  • Subtraction: Given operand1 - operand2, where each operand must be of character or numeric type, subtract operand2 from operand1 and return the difference. Example: 4 - 6.
  • Postdecrement: Given variable--, 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: x--;.
  • Postincrement: Given variable++, 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: x++;.
  • Predecrement: Given --variable, 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: --x;.
  • Preincrement: Given ++variable, 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: ++x;.
  • String concatenation: Given operand1 + operand2, where at least one operand is of String type, append operand2's string representation to operand1'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], where index must be of integer (int) type, read a value from or store a value into variable's storage element at location index. 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;.

Bitwise operators

1 2 3 4 Page 1
Page 1 of 4