Book Home Java Enterprise in a Nutshell Search this book

2.5. Expressions and Operators

So far in this chapter, we've learned about the primitive types that Java programs can manipulate and seen how to include primitive values as literals in a Java program. We've also used variables as symbolic names that represent, or hold, values. These literals and variables are the tokens out of which Java programs are built.

An expression is the next higher level of structure in a Java program. The Java interpreter evaluates an expression to compute its value. The very simplest expressions are called primary expressions and consist of literals and variables. So, for example, the following are all expressions:

1.7         // An integer literal
true        // A boolean literal
sum         // A variable

When the Java interpreter evaluates a literal expression, the resulting value is the literal itself. When the interpreter evaluates a variable expression, the resulting value is the value stored in the variable.

Primary expressions are not very interesting. More complex expressions are made by using operators to combine primary expressions. For example, the following expression uses the assignment operator to combine two primary expressions--a variable and a floating-point literal--into an assignment expression:

sum = 1.7

But operators are used not only with primary expressions; they can also be used with expressions at any level of complexity. Thus, the following are all legal expressions:

sum = 1 + 2 + 3*1.2 + (4 + 8)/3.0
sum/Math.sqrt(3.0 * 1.234)
(int)(sum + 33)

2.5.1. Operator Summary

The kinds of expressions you can write in a programming language depend entirely on the set of operators available to you. Table 2-5 summarizes the operators available in Java. The P and A columns of the table specify the precedence and associativity of each group of related operators, respectively.

Table 2-5. Java Operators

PAOperatorOperand Type(s)Operation Performed
15L.object, memberobject member access
[]array, intarray element access
( args )method, arglistmethod invocation
++, − −variablepost-increment, decrement
14R++, − −variablepre-increment, decrement
+, numberunary plus, unary minus
~integerbitwise complement
!booleanboolean NOT
13Rnewclass, arglistobject creation
( type )type, anycast (type conversion)
12L*, /, %number, number

multiplication, division, remainder

11L+, number, number

addition, subtraction

+string, any

string concatenation

10L<<integer, integer

left shift

>>integer, integer

right shift with sign extension

>>>integer, integer

right shift with zero extension

9L<, <=number, number

less than, less than or equal

>, >=number, number

greater than, greater than or equal

instanceofreference, type

type comparison

8L= =primitive, primitive

equal (have identical values)

!=primitive, primitive

not equal (have different values)

= =reference, reference

equal (refer to same object)

!=reference, reference

not equal (refer to different objects)

7L&integer, integer

bitwise AND

&boolean, boolean

boolean AND

6L^integer, integer

bitwise XOR

^boolean, boolean

boolean XOR

5L|integer, integer

bitwise OR

|boolean, boolean

boolean OR

4L&&boolean, boolean

conditional AND

3L||boolean, boolean

conditional OR

2R?:boolean, any, any

conditional (ternary) operator

1R=variable, any

assignment

*=, /=, %=, variable, any

assignment with operation

+=, −=, <<=,
>>=, >>>=,
&=, ^=, |=

2.5.1.1. Precedence

The P column of Table 2-5 specifies the precedence of each operator. Precedence specifies the order in which operations are performed. Consider this expression:

a + b * c      

The multiplication operator has higher precedence than the addition operator, so a is added to the product of b and c. Operator precedence can be thought of as a measure of how tightly operators bind to their operands. The higher the number, the more tightly they bind.

Default operator precedence can be overridden through the use of parentheses, to explicitly specify the order of operations. The previous expression can be rewritten as follows to specify that the addition should be performed before the multiplication:

(a + b) * c

The default operator precedence in Java was chosen for compatibility with C; the designers of C chose this precedence so that most expressions can be written naturally without parentheses. There are only a few common Java idioms for which parentheses are required. Examples include:

// Class cast combined with member access
((Integer) o).intValue();

// Assignment combined with comparison
while((line = in.readLine()) != null) { ... }

// Bitwise operators combined with comparison
if ((flags & (PUBLIC | PROTECTED)) != 0) { ... }

2.5.1.2. Associativity

When an expression involves several operators that have the same precedence, the operator associativity governs the order in which the operations are performed. Most operators are left-to-right associative, which means that the operations are performed from left to right. The assignment and unary operators, however, have right-to-left associativity. The A column of Table 2-5 specifies the associativity of each operator or group of operators. The value L means left to right, and R means right to left.

The additive operators are all left-to-right associative, so the expression a+b-c is evaluated from left to right: (a+b)-c. Unary operators and assignment operators are evaluated from right to left. Consider this complex expression:

a = b += c = -~d

This is evaluated as follows:

a = (b += (c = -(~d)))

As with operator precedence, operator associativity establishes a default order of evaluation for an expression. This default order can be overridden through the use of parentheses. However, the default operator associativity in Java has been chosen to yield a natural expression syntax, and you rarely need to alter it.

2.5.1.3. Operand number and type

The fourth column of Table 2-5 specifies the number and type of the operands expected by each operator. Some operators operate on only one operand; these are called unary operators. For example, the unary minus operator changes the sign of a single number:

-n             // The unary minus operator

Most operators, however, are binary operators that operate on two operand values. The operator actually comes in both forms:

a - b          // The subtraction operator is a binary operator

Java also defines one ternary operator, often called the conditional operator. It is like an if statement inside an expression. Its three operands are separated by a question mark and a colon; the second and third operators must both be of the same type:

x > y ? x : y  // Ternary expression; evaluates to the larger of x and y

In addition to expecting a certain number of operands, each operator also expects particular types of operands. Column four of the table lists the operand types. Some of the codes used in that column require further explanation:

number

An integer, floating-point value, or character (i.e., any primitive type except boolean)

integer

A byte, short, int, long, or char value (long values are not allowed for the array access operator [])

reference

An object or array

variable

A variable or anything else, such as an array element, to which a value can be assigned

2.5.1.4. Return type

Just as every operator expects its operands to be of specific types, each operator produces a value of a specific type. The arithmetic, increment and decrement, bitwise, and shift operators return a double if at least one of the operands is a double. Otherwise, they return a float if at least one of the operands is a float. Otherwise, they return a long if at least one of the operands is a long. Otherwise, they return an int, even if both operands are byte, short, or char types that are narrower than int.

The comparison, equality, and boolean operators always return boolean values. Each assignment operator returns whatever value it assigned, which is of a type compatible with the variable on the left side of the expression. The conditional operator returns the value of its second or third argument (which must both be of the same type).

2.5.1.5. Side effects

Every operator computes a value based on one or more operand values. Some operators, however, have side effects in addition to their basic evaluation. If an expression contains side effects, evaluating it changes the state of a Java program in such a way that evaluating the expression again may yield a different result. For example, the ++ increment operator has the side effect of incrementing a variable. The expression ++a increments the variable a and returns the newly incremented value. If this expression is evaluated again, the value will be different. The various assignment operators also have side effects. For example, the expression a*=2 can also be written as a=a*2. The value of the expression is the value of a multiplied by 2, but the expression also has the side effect of storing that value back into a. The method invocation operator () has side effects if the invoked method has side effects. Some methods, such as Math.sqrt(), simply compute and return a value without side effects of any kind. Typically, however, methods do have side effects. Finally, the new operator has the profound side effect of creating a new object.

2.5.1.6. Order of evaluation

When the Java interpreter evaluates an expression, it performs the various operations in an order specified by the parentheses in the expression, the precedence of the operators, and the associativity of the operators. Before any operation is performed, however, the interpreter first evaluates the operands of the operator. (The exceptions are the &&, ||, and ?: operators, which do not always evaluate all their operands.) The interpreter always evaluates operands in order from left to right. This matters if any of the operands are expressions that contain side effects. Consider this code, for example:

int a = 2;
int v = ++a + ++a * ++a;

Although the multiplication is performed before the addition, the operands of the + operator are evaluated first. Thus, the expression evaluates to 3+4*5, or 23.

2.5.2. Arithmetic Operators

Since most programs operate primarily on numbers, the most commonly used operators are often those that perform arithmetic operations. The arithmetic operators can be used with integers, floating-point numbers, and even characters (i.e., they can be used with any primitive type other than boolean). If either of the operands is a floating-point number, floating-point arithmetic is used; otherwise, integer arithmetic is used. This matters because integer arithmetic and floating-point arithmetic differ in the way division is performed and in the way underflows and overflows are handled, for example. The arithmetic operators are:

Addition (+)

The + operator adds two numbers. As we'll see shortly, the + operator can also be used to concatenate strings. If either operand of + is a string, the other one is converted to a string as well. Be sure to use parentheses when you want to combine addition with concatenation. For example:

System.out.println("Total: " + 3 + 4);    // Prints "Total: 34", not 7!

Subtraction ()

When is used as a binary operator, it subtracts its second operand from its first. For example, 7-3 evaluates to 4. The operator can perform unary negation.

Multiplication (*)

The * operator multiplies its two operands. For example, 7*3 evaluates to 21.

Division (/)

The / operator divides its first operand by its second. If both operands are integers, the result is an integer, and any remainder is lost. If either operand is a floating-point value, however, the result is a floating-point value. When dividing two integers, division by zero throws an ArithmeticException. For floating-point calculations, however, division by zero simply yields an infinite result or NaN:

7/3          // Evaluates to 2
7/3.0f       // Evaluates to 2.333333f
7/0          // Throws an ArithmeticException
7/0.0        // Evaluates to positive infinity
0.0/0.0      // Evaluates to NaN

Modulo (%)

The % operator computes the first operand modulo the second operand (i.e., it returns the remainder when the first operand is divided by the second operand an integral number of times). For example, 7%3 is 1. The sign of the result is the same as the sign of the first operand. While the modulo operator is typically used with integer operands, it also works for floating-point values. For example, 4.3%2.1 evaluates to 0.1. When operating with integers, trying to compute a value modulo zero causes an ArithmeticException. When working with floating-point values, anything modulo 0.0 evaluates to NaN, as does infinity modulo anything.

Unary Minus ()

When is used as a unary operator, before a single operand, it performs unary negation. In other words, it converts a positive value to an equivalently negative value, and vice versa.

2.5.3. String Concatenation Operator

In addition to adding numbers, the + operator (and the related += operator) also concatenates, or joins, strings. If either of the operands to + is a string, the operator converts the other operand to a string. For example:

System.out.println("Quotient: " + 7/3.0f);  // Prints "Quotient: 2.3333333"

As a result, you must be careful to put any addition expressions in parentheses when combining them with string concatenation. If you do not, the addition operator is interpreted as a concatenation operator.

The Java interpreter has built-in string conversions for all primitive types. An object is converted to a string by invoking its toString() method. Some classes define custom toString() methods, so that objects of that class can easily be converted to strings in this way. An array is converted to a string by invoking the built-in toString() method, which, unfortunately, does not return a useful string representation of the array contents.

2.5.4. Increment and Decrement Operators

The ++ operator increments its single operand, which must be a variable, an element of an array, or a field of an object, by one. The behavior of this operator depends on its position relative to the operand. When used before the operand, where it is known as the pre-increment operator, it increments the operand and evaluates to the incremented value of that operand. When used after the operand, where it is known as the post-increment operator, it increments its operand, but evaluates to the value of that operand before it was incremented.

For example, the following code sets both i and j to 2:

i = 1;
j = ++i;

But these lines set i to 2 and j to 1:

i = 1;
j = i++;

Similarly, the − − operator decrements its single numeric operand, which must be a variable, an element of an array, or a field of an object, by one. Like the ++ operator, the behavior of − − depends on its position relative to the operand. When used before the operand, it decrements the operand and returns the decremented value. When used after the operand, it decrements the operand, but returns the un-decremented value.

The expressions x++ and x− − are equivalent to x=x+1 and x=x−1, respectively, except that when using the increment and decrement operators, x is only evaluated once. If x is itself an expression with side effects, this makes a big difference. For example, these two expressions are not equivalent:

a[i++]++;             // Increments an element of an array
a[i++] = a[i++] + 1;  // Adds one to an array element and stores it in another

These operators, in both prefix and postfix forms, are most commonly used to increment or decrement the counter that controls a loop.

2.5.5. Comparison Operators

The comparison operators consist of the equality operators that test values for equality or inequality and the relational operators used with ordered types (numbers and characters) to test for greater than and less than relationships. Both types of operators yield a boolean result, so they are typically used with if statements and while and for loops to make branching and looping decisions. For example:

if (o != null) ...;           // The not equals operator
while(i < a.length) ...;      // The less than operator

Java provides the following equality operators:

Equals (= =)

The = = operator evaluates to true if its two operands are equal and false otherwise. With primitive operands, it tests whether the operand values themselves are identical. For operands of reference types, however, it tests whether the operands refer to the same object or array. In other words, it does not test the equality of two distinct objects or arrays. In particular, note that you cannot test two distinct strings for equality with this operator.

If = = is used to compare two numeric or character operands that are not of the same type, the narrower operand is converted to the type of the wider operand before the comparison is done. For example, when comparing a short to a float, the short is first converted to a float before the comparison is performed. For floating-point numbers, the special negative zero value tests equal to the regular, positive zero value. Also, the special NaN (not-a-number) value is not equal to any other number, including itself. To test whether a floating-point value is NaN, use the Float.isNan() or Double.isNan() method.

Not Equals (!=)

The != operator is exactly the opposite of the = = operator. It evaluates to true if its two primitive operands have different values or if its two reference operands refer to different objects or arrays. Otherwise, it evaluates to false.

The relational operators can be used with numbers and characters, but not with boolean values, objects, or arrays because those types are not ordered. Java provides the following relational operators:

Less Than (<)

Evaluates to true if the first operand is less than the second.

Less Than or Equal (<=)

Evaluates to true if the first operand is less than or equal to the second.

Greater Than (>)

Evaluates to true if the first operand is greater than the second.

Greater Than or Equal (>=)

Evaluates to true if the first operand is greater than or equal to the second.

2.5.6. Boolean Operators

As we've just seen, the comparison operators compare their operands and yield a boolean result, which is often used in branching and looping statements. In order to make branching and looping decisions based on conditions more interesting than a single comparison, you can use the Boolean (or logical) operators to combine multiple comparison expressions into a single, more complex, expression. The Boolean operators require their operands to be boolean values and they evaluate to boolean values. The operators are:

Conditional AND (&&)

This operator performs a Boolean AND operation on its operands. It evaluates to true if and only if both its operands are true. If either or both operands are false, it evaluates to false. For example:

if (x < 10 && y > 3) ... // If both comparisons are true

This operator (and all the Boolean operators except the unary ! operator) have a lower precedence than the comparison operators. Thus, it is perfectly legal to write a line of code like the one above. However, some programmers prefer to use parentheses to make the order of evaluation explicit:

if ((x < 10) && (y > 3)) ... 

You should use whichever style you find easier to read.

This operator is called a conditional AND because it conditionally evaluates its second operand. If the first operand evaluates to false, the value of the expression is false, regardless of the value of the second operand. Therefore, to increase efficiency, the Java interpreter takes a shortcut and skips the second operand. Since the second operand is not guaranteed to be evaluated, you must use caution when using this operator with expressions that have side effects. On the other hand, the conditional nature of this operator allows us to write Java expressions such as the following:

if (data != null && i < data.length && data[i] != -1) ... 

The second and third comparisons in this expression would cause errors if the first or second comparisons evaluated to false. Fortunately, we don't have to worry about this because of the conditional behavior of the && operator.

Conditional OR (||)

This operator performs a Boolean OR operation on its two boolean operands. It evaluates to true if either or both of its operands are true. If both operands are false, it evaluates to false. Like the && operator, || does not always evaluate its second operand. If the first operand evaluates to true, the value of the expression is true, regardless of the value of the second operand. Thus, the operator simply skips that second operand in that case.

Boolean NOT (!)

This unary operator changes the boolean value of its operand. If applied to a true value, it evaluates to false, and if applied to a false value, it evaluates to true. It is useful in expressions like these:

if (!found) ...          // found is a boolean variable declared somewhere
while (!c.isEmpty()) ... // The isEmpty() method returns a boolean value

Because ! is a unary operator, it has a high precedence and often must be used with parentheses:

if (!(x > y && y > z)) 

Boolean AND (&)

When used with boolean operands, the & operator behaves like the && operator, except that it always evaluates both operands, regardless of the value of the first operand. This operator is almost always used as a bitwise operator with integer operands, however, and many Java programmers would not even recognize its use with boolean operands as legal Java code.

Boolean OR (|)

This operator performs a Boolean OR operation on its two boolean operands. It is like the || operator, except that it always evaluates both operands, even if the first one is true. The | operator is almost always used as a bitwise operator on integer operands; its use with boolean operands is very rare.

Boolean XOR (^)

When used with boolean operands, this operator computes the Exclusive OR (XOR) of its operands. It evaluates to true if exactly one of the two operands is true. In other words, it evaluates to false if both operands are false or if both operands are true. Unlike the && and || operators, this one must always evaluate both operands. The ^ operator is much more commonly used as a bitwise operator on integer operands. With boolean operands, this operator is equivalent to the != operator.

2.5.7. Bitwise and Shift Operators

The bitwise and shift operators are low-level operators that manipulate the individual bits that make up an integer value. The bitwise operators are most commonly used for testing and setting individual flag bits in a value. In order to understand their behavior, you must understand binary (base-2) numbers and the twos-complement format used to represent negative integers. You cannot use these operators with floating-point, boolean, array, or object operands. When used with boolean operands, the &, |, and ^ operators perform a different operation, as described in the previous section.

If either of the arguments to a bitwise operator is a long, the result is a long. Otherwise, the result is an int. If the left operand of a shift operator is a long, the result is a long; otherwise, the result is an int. The operators are:

Bitwise Complement (~)

The unary ~ operator is known as the bitwise complement, or bitwise NOT, operator. It inverts each bit of its single operand, converting ones to zeros and zeros to ones. For example:

byte b = ~12;           // ~00000110 ==> 11111001 or -13 decimal
flags = flags & ~f;     // Clear flag f in a set of flags

Bitwise AND (&)

This operator combines its two integer operands by performing a Boolean AND operation on their individual bits. The result has a bit set only if the corresponding bit is set in both operands. For example:

10 & 7                   // 00001010 & 00000111 ==> 00000010 or 2
if ((flags & f) != 0)    // Test whether flag f is set

When used with boolean operands, & is the infrequently used Boolean AND operator described earlier.

Bitwise OR (|)

This operator combines its two integer operands by performing a Boolean OR operation on their individual bits. The result has a bit set if the corresponding bit is set in either or both of the operands. It has a zero bit only where both corresponding operand bits are zero. For example:

10 | 7               // 00001010 | 00000111 ==> 00001111 or 15
flags = flags | f;   // Set flag f

When used with boolean operands, | is the infrequently used Boolean OR operator described earlier.

Bitwise XOR (^)

This operator combines its two integer operands by performing a Boolean XOR (Exclusive OR) operation on their individual bits. The result has a bit set if the corresponding bits in the two operands are different. If the corresponding operand bits are both ones or both zeros, the result bit is a zero. For example:

10 & 7               // 00001010 ^ 00000111 ==> 00001101 or 13

When used with boolean operands, ^ is the infrequently used Boolean XOR operator.

Left Shift (<<)

The << operator shifts the bits of the left operand left by the number of places specified by the right operand. High-order bits of the left operand are lost, and zero bits are shifted in from the right. Shifting an integer left by n places is equivalent to multiplying that number by 2n. For example:

10 << 1    // 00001010 << 1 = 00010100 = 20 = 10*2
7 << 3     // 00000111 << 3 = 00111000 = 56 = 7*8
-1 << 2    // 0xFFFFFFFF << 2 = 0xFFFFFFFC = -4 = -1*4

If the left operand is a long, the right operand should be between 0 and 63. Otherwise, the left operand is taken to be an int, and the right operand should be between 0 and 31.

Signed Right Shift (>>)

The >> operator shifts the bits of the left operand to the right by the number of places specified by the right operand. The low-order bits of the left operand are shifted away and are lost. The high-order bits shifted in are the same as the original high-order bit of the left operand. In other words, if the left operand is positive, zeros are shifted into the high-order bits. If the left operand is negative, ones are shifted in instead. This technique is known as sign extension; it is used to preserve the sign of the left operand. For example:

10 >> 1      // 00001010 >> 1 = 00000101 = 5 = 10/2
27 >> 3      // 00011011 >> 3 = 00000011 = 3 = 27/8
-50 >> 2     // 11001110 >> 2 = 11110011 = -13 != -50/4

If the left operand is positive and the right operand is n, the >> operator is the same as integer division by 2n.

Unsigned Right Shift (>>>)

This operator is like the >> operator, except that it always shifts zeros into the high-order bits of the result, regardless of the sign of the left-hand operand. This technique is called zero extension ; it is appropriate when the left operand is being treated as an unsigned value (despite the fact that Java integer types are all signed). Examples:

-50 >>> 2     // 11001110 >>> 2 = 00110011 = 51
0xff >>> 4    // 11111111 >>> 4 = 00001111 = 15  = 255/16

2.5.8. Assignment Operators

The assignment operators store, or assign, a value into some kind of variable. The left operand must evaluate to an appropriate local variable, array element, or object field. The right side can be any value of a type compatible with the variable. An assignment expression evaluates to the value that is assigned to the variable. More importantly, however, the expression has the side effect of actually performing the assignment. Unlike all other binary operators, the assignment operators are right-associative, which means that the assignments in a=b=c are performed right-to-left, as follows: a=(b=c).

The basic assignment operator is =. Do not confuse it with the equality operator, = =. In order to keep these two operators distinct, I recommend that you read = as "is assigned the value."

In addition to this simple assignment operator, Java also defines 11 other operators that combine assignment with the 5 arithmetic operators and the 6 bitwise and shift operators. For example, the += operator reads the value of the left variable, adds the value of the right operand to it, stores the sum back into the left variable as a side effect, and returns the sum as the value of the expression. Thus, the expression x+=2 is almost the same x=x+2. The difference between these two expressions is that when you use the += operator, the left operand is evaluated only once. This makes a difference when that operand has a side effect. Consider the following two expressions, which are not equivalent:

a[i++] += 2;
a[i++] = a[i++] + 2;

The general form of these combination assignment operators is:

var op= value

This is equivalent (unless there are side effects in var) to:

var = var op value

The available operators are:

+=    −=    *=    /=    %=    // Arithmetic operators plus assignment
&=    |=    ^=                // Bitwise operators plus assignment
<<=   >>=   >>>=              // Shift operators plus assignment

The most commonly used operators are += and − =, although &= and |= can also be useful when working with boolean flags. For example:

i += 2;          // Increment a loop counter by 2
c −= 5;          // Decrement a counter by 5
flags |= f;      // Set a flag f in an integer set of flags
flags &= ~f;     // Clear a flag f in an integer set of flags

2.5.9. The Conditional Operator

The conditional operator ?: is a somewhat obscure ternary (three-operand) operator inherited from C. It allows you to embed a conditional within an expression. You can think of it as the operator version of the if/else statement. The first and second operands of the conditional operator are separated by a question mark (?), while the second and third operands are separated by a colon (:). The first operand must evaluate to a boolean value. The second and third operands can be of any type, but they must both be of the same type.

The conditional operator starts by evaluating its first operand. If it is true, the operator evaluates its second operand and uses that as the value of the expression. On the other hand, if the first operand is false, the conditional operator evaluates and returns its third operand. The conditional operator never evaluates both its second and third operand, so be careful when using expressions with side effects with this operator. Examples of this operator are:

int max = (x > y) ? x : y;
String name = (name != null) ? name : "unknown";

Note that the ?: operator has lower precedence than all other operators except the assignment operators, so parentheses are not usually necessary around the operands of this operator. Many programmers find conditional expressions easier to read if the first operand is placed within parentheses, however. This is especially true because the conditional if statement always has its conditional expression written within parentheses.

2.5.10. The instanceof Operator

The instanceof operator requires an object or array value as its left operand and the name of a reference type as its right operand. It evaluates to true if the object or array is an instance of the specified type; it returns false otherwise. If the left operand is null, instanceof always evaluates to false. If an instanceof expression evaluates to true, it means that you can safely cast and assign the left operand to a variable of the type of the right operand.

The instanceof operator can be used only with array and object types and values, not primitive types and values. Object and array types are discussed in detail later in this chapter. Examples of instanceof are:

"string" instanceof String      // True: all strings are instances of String
"" instanceof Object            // True: strings are also instances of Object
new int[] {1} instanceof int[]  // True: the array value is an int array
new int[] {1} instanceof byte[] // False: the array value is not a byte array
new int[] {1} instanceof Object // True: all arrays are instances of Object
null instanceof String          // False: null is never instanceof anything

// Use instanceof to make sure that it is safe to cast an object
if (object instanceof Point) {
  Point p = (Point) object;
}

2.5.11. Special Operators

There are five language constructs in Java that are sometimes considered operators and sometimes considered simply part of the basic language syntax. These "operators" are listed in Table 2-5 in order to show their precedence relative to the other true operators. The use of these language constructs is detailed elsewhere in this chapter, but is described briefly here, so that you can recognize these constructs when you encounter them in code examples:

Object member access (.)

An object is a collection of data and methods that operate on that data; the data fields and methods of an object are called its members. The dot (.) operator accesses these members. If o is an expression that evaluates to an object reference, and f is the name of a field of the object, o.f evaluates to the value contained in that field. If m is the name of a method, o.m refers to that method and allows it to be invoked using the () operator shown later.

Array element access ([])

An array is a numbered list of values. Each element of an array can be referred to by its number, or index. The [] operator allows you to refer to the individual elements of an array. If a is an array, and i is an expression that evaluates to an int, a[i] refers to one of the elements of a. Unlike other operators that work with integer values, this operator restricts array index values to be of type int or narrower.

Method invocation (())

A method is a named collection of Java code that can be run, or invoked, by following the name of the method with zero or more comma-separated expressions contained within parentheses. The values of these expressions are the arguments to the method. The method processes the arguments and optionally returns a value that becomes the value of the method invocation expression. If o.m is a method that expects no arguments, the method can be invoked with o.m(). If the method expects three arguments, for example, it can be invoked with an expression such as o.m(x,y,z). Before the Java interpreter invokes a method, it evaluates each of the arguments to be passed to the method. These expressions are guaranteed to be evaluated in order from left to right (which matters if any of the arguments have side effects).

Object creation (new)

In Java, objects are created with the new operator, which is followed by the type of the object to be created and a parenthesized list of arguments to be passed to the object constructor. A constructor is a special method that initializes a newly created object, so the object creation syntax is similar to the Java method invocation syntax. For example:

new ArrayList();
new Point(1,2)

Type conversion or casting (())

As we've already seen, parentheses can also be used as an operator to perform narrowing type conversions, or casts. The first operand of this operator is the type to be converted to; it is placed between the parentheses. The second operand is the value to be converted; it follows the parentheses. For example:

(byte) 28          // An integer literal cast to a byte type
(int) (x + 3.14f)  // A floating-point sum value cast to an integer value
(String)h.get(k)   // A generic object cast to a more specific string type



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.