- Using Visual J++ -

Chapter 10

Java Language Fundamentals


In this chapter, you will learn all about Java's extensive collection of operators. An operator is a symbol that performs work. The work is usually mathematical or logical work. The standard calculator-style operators are joined by several bitwise and comparison operators so that you can manipulate and test data in any manner needed.

The Java operators are numerous. C and C++ programmers will have little trouble mastering these operators because of their close relation to C and C++ operators. If you've programmed in other languages, you might be surprised how many operators exist in Java. If you've never programmed before, that's okay also because this chapter shows you many examples. You don't have to be a math whiz to master Java's operators. Java does all the calculating as long as you set up the expressions properly.

Defining Java Data

Programs process data. Therefore, the logical starting point when learning a new programming language is to learn how to specify data values that your program will manipulate, manage, and calculate. The object-oriented nature of Java makes the data even more precious because the data drives the programs, whereas in procedural programming languages (the opposite of object-oriented languages), the programs drive the data. You, as a user of programs, are only interested in the data. The data might be payroll figures, windows of text, or name and address records. Whatever the data, the program's user wants to see the correct manipulations of data so the user sees the correct data-based answers.

Two broad kinds of data exist in Java: literals and variables. A literal value is a constant value that does not change, such as your first name or date of birth. A variable is a storage place for changing data. Therefore, a Java program might use a variable to hold a customer's current balance or a monthly net pay figure.

Literals

A literal is obvious and easy to understand. A literal is just a number, character, or string of characters. Several kinds of Java literals exist. A number is a literal. Java supports integer (whole numbers without decimal places) and floating point (numbers with decimal places) literals. Here are some valid integer literals:

An integer literal can fall in the range of -9.22337e18 to +9.22337e18. Therefore, Java supports virtually any size of integer literal you'll ever need.

 
If those numbers look strange to you, it's because I listed them in scientific notation. Scientific notation is a shortcut notation that lets one express extremely small or extremely large numbers in a small amount of space. To convert a scientific notational number to its actual form, multiply the number to the left of the e (which stands for exponent) to 10 times the number on the right of the e. Therefore, 9.22337e18 is the same as 9.22337 times 1 followed by 18 zeroes, or a very large number indeed!
 
 
Java supports hexadecimal (base-16) and octal (base-8) integers. A hexadecimal integer literal begins with 0x or 0X. Therefore, the hexadecimal value 0x12 is the same as the decimal (base-10) integer literal 18. An octal literal always begins with a leading 0. Therefore, the octal 011 literal is the same as decimal 9.

Here are sample floating-point literals:

When you want to use a literal in a Java program, just type the literal. As you can see, you can enter Java floating-point literals in scientific notation and Java understands the correct value you want expressed.

 
Never use commas or dollar signs in numbers.

Java supports two boolean literals. These boolean literals are true and false. You will use boolean literals to test or set boolean values to true or false to determine if certain events are to occur.

A character literal is a single character. Unlike numeric and boolean literals, you must enclose character literals inside single quotation marks. The following are character literals:

Notice that a character literal does not have to be alphabetic. If you use a number as a character literal, you cannot compute with that number. Therefore, '4' is a character literal but 4 is an integer literal. Enclose only single characters inside the single quotation marks. If you need to represent several characters as a literal, you'll have to use a string literal described at the end of this section.

Java supports some special character literals called escape sequences. Due to the special nature of some character literals, you cannot always represent a character inside single quotation marks. For example, how can you represent the tab character? (In the computer's internal list of characters, a tab consumes one individual character of storage.) Table 10.1 lists Java's escape sequences that consume only a single character of storage (despite the fact that two characters appear inside the single quotes). These characters represent characters you cannot type directly from your keyboard.

Table 10.1 Java's Escape Sequence Character Represent Non-Typable Characters

Escape Sequence Represents
'\b' Backspace
'\f' Formfeed
'\n' Newline (linefeed followed by a carriage return)
'\r' Carriage return
'\t' Tab (horizontal)
'\'' Single quotation mark
'\"' Double quotation mark
'\xxx' Octal escape literal where xxx represents an octal ASCII number

You could use an escape character to move the cursor down a line (with the linefeed escape sequence) or you could use one to place a single quotation mark on a window (you could not represent a single quote by placing it inside two single quotes like this: ''').

The final escape sequence character table 10.1 shows represents any ASCII character. Therefore, you can specify any ASCII character literal by enclosing the ASCII character's octal number inside the escape sequence. '\101' represents the single character A, for example. Although 'A' is easier to type, the octal escape sequence lets you represent even non-printing ASCII characters such as those below ASCII 31. If you want to represent the escape character, the ASCII decimal value of 27, you can do so with this octal escape sequence: '\033' (33 is the octal equivalent of decimal 27).

Specify string literals by enclosing the string literals inside quotation marks. Therefore, all of the following items are string literals:

Represent the empty string or null string by typing two quotation marks with nothing inside of them (not even a space). As with a character literal, when you enclose numbers inside quotation marks, the numbers are only strings of characters and you cannot perform calculations with the string. In addition, a single character inside quotation marks is a string but a single character inside a single quotation mark is a single character.

 
You can place an escape character inside a string. Therefore, the following string literal contains starting and ending quotation marks: "\"Java\"".

Identifiers as Variables

The reason you should understand literals is because you'll often store literals in program variables. A variable is a named storage location that holds data. Each of your computer memory location's has a unique address just as each house in your town has a unique address. Your data resides in memory at a memory address. Instead of making you remember specific cryptic numeric memory addresses, Java lets you create and name those variables. Thereafter, when you refer to a variable named age, Java will find that variable's address instead of making you refer to the address in your program. Figure 10.1 illustrates how a named storage variable location is easier to remember than its address.


FIG. 10.1

Store your data in variables and you don't have to remember cryptic addresses.

You are in charge of naming variables. When you need a variable, you must tell Java that you want one, you must tell Java the name that you want to assign to the variable, and you must tell Java the data type of the variable. Since you are responsible for naming variables, you should understand the variable-naming rules. In Java, and in most programming languages, variable names must follow the same naming rules as all identifiers. An identifier can be any of the following language items:

As you can see, once you learn how to name identifiers, you'll not only know the rules for naming variables, but you'll also understand the rules for naming other items in the Java language.

 
You will understand the purpose for all these identifiers as you progress in Java programming.

Follow these identifier naming rules when you create identifiers:

  1. An identifier cannot be the same name as a Java command or supplied class or built-in function.
  2. All identifiers must begin with an alphabetic letter.
  3. Identifier names can contain letters, numbers, the underscore character, and the dollar sign.
  4. Identifier names are case sensitive. Therefore, if you name a variable MyAmt, you cannot reference that variable later in the program as myamt or MYAMT.
  5. The length of identifiers is practically unlimited (limited by your system's file size).
  6. Although not a requirement, you should select identifier names that well identify the data they hold. Therefore, salesTax would be a good name for a variable holding a sales tax calculation, whereas, x4$w23 would be a terrible name for such a value even though both names are legal identifiers.

All of the following are valid identifiers and make valid variable names because they follow the identifier naming rules:

Defining Various Variables

When you define (create) a variable in a program, you request that Java reserve memory storage for that variable and you must specify the data type and variable name. The types of variables you can define closely match the types of literals that you learned about in the previous sections. When you want to store a single character in a variable, for example, you should define a character variable and not a floating-point variable.

Java's variable types break down into several subtypes that you don't have to worry about when dealing with literals. For example, Java supports four types of integer variables. The types exist so that you can define the appropriate storage area without reserving too much space for your data. In other words, if you are going to store a single integer digit, you should define a small integer variable type (called a byte as you're getting ready to see) but if you need to store extremely large or extreme negative integers, you would want to define a larger integer variable type (such as a long integer). The larger integer types consume much more memory than the smaller ones.

 
Don't define a larger variable size than your data requires. Remember, your Java programs run primarily on other people's machines when they load your Web page. Don't consume more of your user's memory resources than necessary. Never reserve a huge variable type when your data requires a smaller variable type. Your programs will load and run faster if you utilize your end-user's memory efficiently.

Integer Variables

Table 10.2 lists the four kinds of integer variables Java supports. The variable's range determines which one you want to use. For example, if you need to store people's ages, you can use bytes. If, however, you want to keep track of larger values, such as the number of times per month people access a particular Web site, you'll probably need a short integer or a regular integer (called int). You cannot squeeze a large value into a variable type too small to hold that value so be on constant guard that you define large enough variables but not too large.

Table 10.2 The Java Integer Variable Sizes

Integer Name Storage Requirement Data Range
byte 1 byte (8 bits) -127 to +128
short 2 bytes (16 bits) -32,767 to +32,768
int 4 bytes (32 bits) -2,147,483,647 to +2,147,483,648
long 8 bytes (64 bits) -9.2233e18 to +9.2233e18
 
A byte of memory (8 bits) represents a single character of memory. Therefore, you can store 16 million characters, or byte integers, in 16 million bytes of available memory.

Notice the table's internal storage requirements for the integers. The long integer consumes eight times the memory of the byte. Obviously, the larger integers can eat up memory in a hurry.

Always define variables before you use them. Generally, you'll find variable definitions towards the top of Java applets, at the top of methods, and inside the init() method. To define a variable, use table 10.2's first column to tell Java the kinds of variables you require. The following statement defines an integer variable named numKeys:

int numKeys; // Defines a 4-byte integer variable

Comment but Don't Over Comment

Use ample comments to explain your program to anyone who might look at your code in the future. When part of your code gets tedious, use ample comments before the code's section and to the right of especially cryptic lines to explain what's happening.
 
Many lines need no comments, however. For example, the comment to the right of the previous numKeys integer definition is redundant. These chapters are using such redundant comments to help you understand the Java language. When you write your actual programs, however, don't use a comment to explain an obvious statement or to teach Java to someone who does not know Java. Use comments to explain, in plain language, what your code is trying to accomplish.
 
A much better numKeys definition comment might look like this:
 
int numKeys; // Holds the number of keystrokes in the user's e-mail address
 
Such a comment explains the true purpose for this particular program's variable definition. Again, for the sake of this book's tutorial, however, you'll see more redundant comments that will help you master Java faster.

Remember to follow your variable definitions, as all executable Java statements, with semicolons. The following statements define four variables, one for each type of Java integer:


byte a;
short b;
int c;
long d;

If you want to define several variables of the same data type, you can place them on separate lines or separate the variable names with commas. The following group of statements


int x;
int y;
int z;

does exactly the same thing as this statement:

int x, y, z; // Defines all 3 on one line

Many programmers prefer to define several variables on the same line.

 
Java defines variables but does not initialize variables for you! Therefore, you do not know what is in the variable x or y or z until you place a value in those variables. Unlike some programming languages, Java does not zero-out variables when you define them. Therefore, be sure to initialize, or place a specific value inside a variable before you use that variable as output or inside a calculation.

Use the assignment operator, =, to assign an initial value to your variables when you define them. Therefore, the following statements define four variables and initialize three of them:


byte f = 32;
int c, d = 7865; // Defines but does not initialize c
long highCount = 0;

Given the previous statements, Java will not initialize c but Java does define c. Later in the program, you would have to store a value in c before using c in another calculation or in output.

Once you've defined a variable, you can store a value in that variable or change the value by placing a different value in the variable. Use the assignment operator to assign values to variables inside the Java program. Assuming that high and low are already defined, you can store values in high and low like this:


high = 9999;
low = -9999;

 
A variable can hold only one value at one time. Therefore, when you store a value in a variable that already has a value, the newer value replaces the older value.
 
 
If you've programmed in C or C++, this is all extremely familiar to you! C and C++ follow basically the same definition and initialization rules although C and C++ do not support all the same kinds of variables as does Java. Java is actually easier than C and C++, however, because Java does not support the unsigned and signed modifiers so you don't have as many combinations to remember.

Floating-Point Variables

Table 10.3 lists the two kinds of floating-point variables that Java supports. You'll use the larger floating-point variable to represent extremely large or small values with a high degree of accuracy. Generally, only scientific and mathematical related programs need the double data types. The digital design of computers does not perfectly represent floating-point values that have many decimal places. For most floating-point calculations, however, the float data type works just fine.

Table 10.3 The Java Floating-Point Variable Sizes

Floating-Point Name Storage Requirement Accuracy
float 4 bytes (32 bits) 6 decimal places
double 8 bytes (64 bits) 14 decimal places

All of the defining and initializing language explanations you learned in the previous section apply to floating-point variables as well as every other kind of variable. Therefore, the following code defines and initializes four floating-point variables:


float w = -234e3; // You can use scientific notation
float x = 4.543;
Double y = -0.9293943444, z = -2.1e-9;

You could later assign different values to these variables like this:


w = 0.0;
x = -9.9;
y = 596.3;
z = 6.20001;

Can you see why these four statements do not include the float or double keywords? These variables are already defined from earlier. Use float and double (and all the other variable definition keywords such as int) only when you define (and optionally initialize at definition time) variables. After definition, you'll use just the variable names.

Boolean Variables

Use the boolean keyword to define boolean variables. A boolean variable can hold only true and false. For example, the following statements define and initialize three boolean variables:


boolean hasPrinted = false;
boolean gotAnswer = false, keyPressed = true;

You'll use boolean variables to hold conditional values. Conditional values are true and false values that determine whether a certain event took place or whether a particular data comparison has been found to be true or false.

 
Do not perform arithmetic on boolean variables. You may only assign true and false values to boolean variables and test boolean variables for true or false contents.

Unlike C, C++, and BASIC-like languages, boolean variables never evaluate to numbers. A boolean variable or expression only translates to true or false.

Character Variables

Define character variables, those variables that will hold only single characters, with the char keyword. The following statements define two character variables:


char firstInitial;
char lastInitial = 'Z';

Assign any of the character literals you learned about in the section named "Literals" including the escape sequences. The following statements both store the letter A in character variables:


c1 = 'A'; // The character literal A
c2 = '\101'; // The octal ASCII value for A

String Variables

Java does not actually support string variables. Well, Java does not technically support string variables. In chapter 13, "Utilizing Pre-Defined Classes," you'll learn how to work with strings as if they were variables. In the meantime, remember these points about so-called string variables:

The following statements define three strings:


String s; // No initialization
String langName = "Java"; // An initialized string
String warning = "Don't press Enter yet!"; // Initialized

The first string, s, really is initialized to a null or empty string. You cannot later assign s a value (or either of the other two defined string variables) with an assignment like this:

s = "Not possible!" // Don't do this!!!!!

You must learn how to use the StringBuffer class, explained in chapter 13, to change strings after defining them.

Assigning Other Variables

Literals are not the only values you place to the right of assignment statements. You can also assign variables to other variables. Assuming you've defined an initialized age, the following assignment stores age's value in a variable named highAge:

highAge = age; // Now, both variables hold the value of age

As you'll see throughout the last half of this chapter, you can also put mathematical expressions to the right of assignment statements and those expressions can hold both literals and variables.

Special Assignments

As you already know, you can only assign boolean variables the boolean literals true or false. In addition, you can assign floating-point variables (and so can Java if a mathematical expression results in such values) the special values of inf and NaN. inf represent infinity, as produced from division by zero and other non-defined mathematical operations. You can test for inf and assign inf if you want to. Nan stands for Not a Number and occurs when an expression produces a non-numerical result (as some inf-based calculations do) . Be sure to check for these values any time your program performs a possibly strange calculation or any time your program might possibly divide by zero.

 
Remember that Java always runs on other people's computers when end-users view your applet's Web page. You don't want your program blowing-up (producing runtime errors) on someone else's machine and neither do the Java developers. Therefore, the inf and NaN results appear so Java does not have to display runtime error messages during a program's execution. The special values place an extra programming burden on you, however, because you'll have to check for these results explicitly and handle them some way if they occur.

Sometimes, you'll need to place a special type suffix character on the end of a numeric literal. Table 10.4 lists the suffix type characters.

Table 10.4 The Java Suffix Type Characters Represent Specific Literal Data Types

Data Type Suffix Internal Storage
l or l Store as long literal
f or F Store as float literal
d or D Store as double literal

When you assign or supply a literal in your program and you want to force Java to use an internal data type representation for that literal, use the suffix character. For example, if you use 1.1 in an expression, Java will use an internal float size to hold the 1.1 value. However, you can force Java to store the 1.1 in a double size (64 bits of storage) for more accuracy in a calculation by suffixing the literal with d (or D) as in 1.1d.

Java also supports the typecast operator. A typecast temporarily changes a literal's or variable's data type while you use the value in an assignment or in an expression. To typecast a literal or variable, precede the value with a data type enclosed in parentheses.

Suppose you've defined numHits to be a byte integer but you want to store numHits in a long integer variable named totalHits. You can typecast numHits like this:

totalHits = (long)numHits; // Temporarily converts numHits's value to long

This typecast does not convert the numHits variable to a long integer, but rather, performs a temporary conversion just at the point of the typecast. Although you will not learn about expressions until the last part of this chapter, the following expression is simple to understand. It adds two numHits values together. Although the example is simplistic and rather foolish, the expression does demonstrate how you can typecast the same variable to two different data types within the same expression.

totalHits = (long)numHits + (short)numHits; // Stores the sum in totalHits

Java performs an internal and automatic typecast when needed. For example, if you assign an integer to a floating-point variable, you don't need to typecast the integer to a floating-point data type first. Generally, you don't have to worry about typecast conversions when storing smaller data types in a larger or higher precision variable. Java usually converts an expression with mixed data types to the highest-precision data type before computing the result. Therefore, a float multiplied by a double variable results in a double result, unless of course, you store the result in a float data typed variable in which case you'll lose some accuracy and Java will have to typecast the answer down to a float before storing the result.

Arrays

An array is a list of variables. The list contains zero or more variables of the same data type that have the same name. For example, you can define an array of five long integers named sizes. The sizes array becomes a table. (Often, an array is called a table.) Figure 10.2 illustrates the way sizes looks to your program.


FIG. 10.2

The representation of an array named sizes

Every item in an array is called an element. sizes, therefore, contains five elements. Even though each sizes element is an integer, and even though every item is called sizes, you'll distinguish between which element you want to initialize or use with a subscript. The first element in an array has a subscript of 0, the second 1, and so on. When you refer to an array element, enclose the subscript in square brackets. Therefore, as figure 10.2 shows, sizes contains five elements and each element is called sizes[0], sizes[1], sizes[2], sizes[3], and sizes[4].

Each of the sizes elements is a variable that you can treat just as you treat any other long integer. The subscripts, however, let you easily step through an array using the controlling and looping language mechanisms you'll learn about in chapter 11, "Controlling Program Flow." In addition to stepping through an array, you can easily define hundreds or even thousands of array element variables with a single statement instead of having to define separately-named variables using the standard defining keywords you learned in the earlier sections of this chapter.

To define an array, use the new command. The new command has several OOP-related benefits and uses but for arrays, new simply tells the Visual J++ compiler that you want a list of array elements. Remember that you can define an array of any data type. The following statements define three arrays of three different data types:


int countList[] = new int[100]; // Define an array of 100 elements
double temps[] = new double[30]; // Define 30 double elements
char initials[] = new char[1000]; // Define 1,000 characters

 
Always keep in mind the array boundaries. The array named temps begins with temps[0] and ends at temps[29]. temps[30] does not exist. Unlike C and C++, Java will not let you reference an array outside its boundaries. Therefore, you cannot store a value in temps[30] or temps[-8] or temps[1923] because none of those elements exist.

Despite their extra definition requirements, once you've define arrays, you can use the array elements just like other variables. For example, the following statements work with individual array elements:


countList[0] = 10;
countList[50] = 394;
temps[2] = 34334.5654;
initials[0] = 'a';
initials[1] = initials[0]; // Use array elements just like non-array variables

Arrays can be large. Generally, you'll define arrays from a series of calculations or load the array data from a data file. You can define and initialize arrays at the same time if you know the values in advance. Enclose the array elements inside braces like this:

byte monthDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

If you define and initialize an array, you don't have to use the new keyword. If you don't supply enough data values to initialize the entire array, Java initializes as many elements as you specify.

 
Java does support multi-dimensioned arrays. Therefore, you can create a table of several dimensions. long chessBoard[][] = new long [8][8]; defines an array of 64 elements, or a 2-dimensional table with 8 rows and 8 columns (each row and column's subscript begins at 0).

If you don't know in advance how many array elements you'll need you can prepare for an array and then define the actual number of elements later. For example, the following statement defines an array with an unknown number of elements:

long answers []; // No array size specified

Suppose the answers array will contain every answer that a user enters correctly in an on-line trivia quiz you send as an applet. Assuming numCorrect is an integer variable that contains the number of correct answers, you could, in the middle of the applet, define the answers array size with this statement:

answers = new long[numCorrect]; // Define the number of array elements

Once you finish with an array (and the array's code ends), Java cleans up the memory reserved with the array. Therefore, unlike C and C++, you do not deallocate array memory.

Operators

Now that you know how to define and initialize data variables, you are ready to learn how to manipulate that data. Java supports several mathematical and conditional operators. You don't have to be a math expert to understand these operators because Java will compute everything for you as long as you set up the expressions correctly.

The following sections quickly explain the Java operators. You might not use all of them in your Java programming. Most of the operators are mathematically related, but several deal with boolean values as well.

The Primary Math Operators

Table 10.5 contains a list of Java's primary math operators. The operators are simple and work mostly like your pocket calculator's equivalent keys work.

Table 10.5 The Java Primary Math Operators Perform Common Math Operations

Operator Name Sample Description
+ Addition 4 + count Adds two values
- Subtraction gross - net Subtracts two values
* Multiplication pay * taxRate Multiplies two values
/ Division bonus / factor Divides two values
% Modulus bonus % factor Computes divisional integer remainder
 
Use only the four integer data types with the modulus operator. Floating-point division produces fractional results with the answer and does not compute a separate remainder.

Suppose you define a floating-point variable named result that held the average number of times the user presses the Enter button per minute. The following statement computes the average:

result = totalEnterHits / numMinutesOnline;

Java supports parentheses. You can use parentheses to group statements together for easier interpretation (by humans) or to override the hierarchy of operations that you'll learn about later in this chapter. The following expression uses parentheses to group the addition before dividing to compute an average:

average = (sales1 + sales2 + sales3 + sales4) / 4;

 
As you'll see later section "Mathematical Hierarchy" section, the previous average calculation would not compute properly without the parentheses.
 
 
The plus sign performs two operations: addition of numerical values and concatenation (also called merging) of string data. Java treats the expression "Trina" + "Donovan" as a single combined string. Java does not automatically insert a blank between concatenated strings, so in this example, the resulting string is "TrinaDonovan". In addition to literals, you can use the string concatenation operator to merge string variables if you like.

The assignment always returns a value and evaluates from right to left. Therefore, you can combine multiple assignments as in the following statement:

a = b = c = d = 0; // Stores 0 in all four variables

Java first assigns the 0 to d and then produces the result of 0 from that specific assignment. Java then takes the resulting 0 and sends the 0 down the line to the c and so on until all four variables receive the zero. Knowing that assignment always produces a value lets you perform some interesting expressions such as this:

expAns = 4 + (x = 3 * p); // assigns 3 * p to x and then adds the result to 4

Incrementing and Decremeting Variables

Often, you'll keep track of a running total or count down from a high total or high score. Java includes the increment and decrement operators you can use to add 1 or subtract 1 from any variable's value. The increment operator is ++ and the decrement operator is --. The following expressions add 1 and subtract 1 from variables:


runningTotal++; // Adds 1 to variable
countDown--; // Subtracts 1 from variable

Increment and decrement give you shortcut operators with which you can perform the common addition and subtraction of 1.

You may place increment or decrement inside expressions such as this:

answer = aVar++ * 4;

One feature of increment and decrement is that you can place these operators on either side of a variable. Prefix notation occurs when you place ++ and -- before the variable and postfix notation occurs when you place ++ and -- after the variable. Therefore, both of the following statements add 1 to their variables:


var1++; // This adds 1 to var1 (postfix)
++var2; // This adds 1 to var2 (prefix)

The increment and decrement operators do have a side effect that can appear if you use the operators inside expressions. Java evaluates the increment or decrement differently depending on which side of the variable you place the operators on. If you use prefix notation, Java performs the increment or decrement before doing anything else in the expression. Assuming x contains 5 before the next statement executes, answer gets the value of 12:

answer = ++x * 2; // Evaluate prefix first

The next statement performs a different calculation, however, due to the postfix notation. Java does not update x until after x is evaluated in the rest of the expression:

answer = x++ * 2; // Evaluate postfix last

In this expression, answer contains 10 because the x is multiplied by 2 before Java updates x. In both expressions, Java increments x so by the next statement in the program, x will always contain 6. The only question is when Java updates x.

Performing Arithmetic Assignments

Often, you'll want to update, or change, the value of a variable based on that variable's existing value. For example, suppose you are keeping track of a 10-question polling result. Every time the user answers a polling questionnaire, you'll add ten to a running total. Any time you want to modify the value of a variable while using that variable's current value in the expression, put the variable on both sides of the assignment operator. Therefore, the following statement adds ten to the variable named totalAnswers:

totalAnswers = totalAnswers + 10; // Adds 10

 
You now know three ways to increment (or decrement) a variable by 1: var = var + 1;, var++; and var += 1;

You could divide a variable by two like this:

aVar = aVar / 2.0; // Compute and store half the variable

This updating of variables occurs so frequently, the Java language developers borrowed common C and C++ operators called the arithmetic assignment operators. Table 10.6 explains these operators.

Table 10.6 The Java Arithmetic Assignment Operators Shorten Some Expressions

Operator Sample Description
+= n += 2 Adds to a variable
-= NetPay -= 10.0 Subtracts from a variable
*= pay *= .7 Multiplies a variable's contents
/= bonus /= x Divides a variable's contents
%= Num %= 1 Computes the remainder based on a variable's current contents

Given table 10.6's operator listing, the following statements use the arithmetic assignments to produce the same results described earlier in this section:


totalAnswers += 10; // Same as totalAnswers = totalAnswers + 10;
aVar /= 2.0; // Same as aVar = aVar / 2.0;

Bitwise Operators

If you're familiar with the internal representation of data, you can use the bitwise operators. The bitwise operators operate on data's internal bits and not on decimal values. Table 10.7 describes the bitwise operators.

Table 10.7 The Java Bitwise Operators Work on Data's Internal Bit Patterns

Operator Sample Description
& aVal & 0x7f Bitwise And
| aVal | 0x01 Bitwise Or
^ aVal ^ 0xCD Bitwise Xor (exclusive Or)
~ aVal ~ 0xFF Bitwise Negation
<< aVal << 3 Bitwise left shift
>> aVal >> 1 Bitwise right shift
>>> aVal >>> 2 Bitwise right shift with zero fill

Programmers commonly use hexadecimal or octal values with the bitwise operators because the hexadecimal and octal values translate so easily to binary.

Suppose that a variable named binVal contains 21. 21 is hexadecimal 0x15 or binary 00010101. The following statements' comments describe the values that Java would store in the target variable named result:


result = binVal & 0xff; // 00010101, or decimal 21
result = binVal | 0xff; // 11111111, or decimal 255
result = binVal ^ 0xf0; // 11101101, or decimal 237
result = ~binVal; // 11101010, or decimal 234
result = binVal << 2; // 01010100, or decimal 84
result = binVal >> 2; // 00000101, or decimal 5
result = binVal >>> 2; // 00000101, or decimal 5

 
The bitwise right shift with zero fill operator, >>>, produces different results from the right shift operator, >>, when you right shift negative numbers. The right shift operator retains the sign bit whereas the right shift with zero fill operator does not retain the sign bit.

In addition to the bitwise operators, Java supports the bitwise assignment operators shown in table 10.8. As with the arithmetic assignment operators, you can use bitwise assignment operators to update the values of variables.

Table 10.8 The Java Bitwise Assignment Operators Shorten Some Bitwise Expressions

Operator Sample Description
&= aVal &= 0x7f Bitwise assignment And
|= aVal |= 0x01 Bitwise assignment Or
^= aVal ^= 0xCD Bitwise assignment Xor (exclusive Or)
~= aVal ~= 0xFF Bitwise assignment Negation
<<= aVal <<= 3 Bitwise assignment left shift
>>= aVal >>= 1 Bitwise assignment right shift
>>>= aVal >>>= 2 Bitwise assignment right shift with zero fill
 
Not every programmer needs bitwise operations. If you don't know how to convert data to binary, you don't have to learn binary to program in the Java language.

Comparison Operators

Table 10.9 describes Java's comparison or relational operators. These operators do not perform mathematical operations but return a boolean true or false value that indicates how one data value relates to another. Several Java statements use the comparison operators to perform their duties. A program needs to be able to make decisions. The comparison operators help Java programs analyze data and make decisions based on that analysis.

Table 10.9 The Java Comparison Operators Compare How Data Values Relate to One Another

Operator Sample Description
== sales == maxSales Compares for equality
!= profit != record Compares for inequality
< n < m Compares for less than
> amt > 0 Compares for greater than
<= top <= bottom Compares for less than or equal to
>= age >= 21 Compares for greater than or equal to
 
The equality operator is not the same as the assignment, =. Java reserves the dual equal sign for making equality comparisons. If you've programmed in C or C++, you know about this distinction. Like C and C++, Java always makes assignments with =. The statement that begins if (ans = 5)... will store 5 in ans. This statement's programmer, however, probably meant to use the equality comparison operator, ==, to test ans.

As you write Java programs, you'll use these comparison operators to compare data values against each other. Java will return true or false based on the result of the comparison. Your program will then be able to execute a statement or not execute a statement based on the result of the comparison. Chapter 11 will use these comparison operators quite extensively to perform work.

Logical Operators

The comparison operators are fine for comparing two values but you can perform additional comparisons inside the same statement by combining comparison operations with each other using the logical operators. Table 10.10 describes the logical operators.

Table 10.10 Combine Two or More Comparison Operators with the Logical Operators

Operator Sample Description
&& sales == maxSales && sales >= 20000 Logical And operator
|| profit != record || profit != oldProfit Logical Or operator
! ! hasOrdered Logical Not operator
 
Use the ! logical Not operator to negate a boolean value. For example, !reachedGoal reads "not reached goal" and you might use such an operation when testing certain data. The ! logical Not operator also works to negate comparison operations. Therefore, !(sales >= maxSales) reads "sales are not greater than or equal to maxSales." Of course, (sales < maxSales) is simpler to understand but the ! operator sometimes comes in handy to negate a comparison that would otherwise be difficult to compare.
 
 
Don't overdo the logical Not operator. Try to code the equivalent positive version of a statement (as shown in the previous tip) before resorting to the !. The ! operator can cloud code.

Java continues the short-circuiting logical operator feature that started in C and C++. If you include two comparison operators on both sides of an Or, ||, and the left side evaluates to true, Java does not evaluate the right side. Therefore, in the following statement:

result = (3 != 9) || (4 > x = 2);

the assignment of 2 to x never takes place! The left side of the Or is true so Java does not evaluate the right side. The purpose of short-circuiting is to add efficiency to your programs but bugs can enter through the short-circuiting feature as well if you count on assignments to take place on one side or the other of a logical operator. Keep tricky code out of your programs; if you want x to receive the 2, assign 2 to x in the statement that precedes this expression. You then can rewrite this expression like so:

result = (3 != 9) || (4 > x); // Short-circuits the right side of ||

without worrying about the assignment.

The And operator short-circuits if the left side is false. Therefore, Java does not interpret the following expression's right side of the And, &&, operator:

result = (5 == 6) && (c < d); // Short-circuits the right side of &&

The bitwise | and & operators do not short-circuit.

The Conditional Operator

The conditional operator is the only Java operator that requires three operands. The conditional operator actually combines if-then-else logic into a simple, clear operation. Although chapter 11 explains if-then-else logic in detail, the conditional operator is simple to understand. The conditional operator returns one of two values depending on the result of a comparison operation.

Here is the general format of the conditional operator:

(comparison) ? true result : false result;

Often, you'll assign a conditional to a variable as in the following statement:

minVal = (a < b) ? a : b;

 
Use parentheses often to visually separate the parts of the conditional statement.

Figure 10.3 shows how minVal receives its data. If the comparison of (a < b) results in a true result, a is assigned to minVal. Otherwise, if (a < b) if false, that is if a is not less than b, the conditional assigns b to minVal. minVal is assigned either a or b. Actually, the conditional illustrates how you can write a minimum operation; the minimum of the two values, either a or b, is assigned to minVal.


FIG. 10.3

The conditional operator returns a value based on a comparison.

 
Don't use the conditional operator as a substitute for all if statements. Use the conditional operator for replacing simple if-then-else logic. Often, however, the complete if statement is clearer to understand and maintain. Clear code is better than short, tricky code that is difficult to maintain.

The conditional can get complex quickly. You don't have to reserve the conditional operator for simple assignments as shown in figure 10.3. The following conditional includes other expressions, including an embedded conditional, inside its operands:

extreme = (x == 1) ? ((a > b) ? a : b) : (f * 6 + 1 - total);

The Operator Hierarchy

The operator hierarchy (also called the order of precedence or operator precedence) determines how multiple operators evaluate in an expression. Consider the following simple expression:

x = 4 + 5 * 2; // 18 or 10?

Expressions do not always evaluate from left to right. In this example, the addition takes place after Java multiples the 5 by 2. Therefore, Java adds the 4 to the multiplicative result of 10. If Java were to add before multiplying, the result would be 18. You can override the operator hierarchy by adding parentheses to group the operators together that you want Java to compute first. The following expression performs the addition first only because of the parentheses:

x = (4 + 5) * 2; // x gets 18

Table 10.11 lists the hierarchical order of operators that Java performs when two or more operators appear inside the same expression. If your mathematical expressions do not produce the results that you expect, you should recheck your expressions to ensure that you've grouped appropriate operators together that you want to evaluate first.

 
You have yet to see all of table 10.11's listed operators.

Table 10.11 Java Evaluates Certain Operators Before Others According to the Internal Operator Hierarchy

Precedence Operators Notes
1 (), [], . Grouping parentheses, array subscript, and the field selector
2 ++, --, !, ~, +, -, instanceof These + and - are unary operators, such as a = -a; or c = +7;
3 *, /, %
4 +, -
5 <<, >>, >>>
6 <, >, <=, >=
7 ==, !=
8 &
9 ^
10 |
11 &&
12 ||
13 ?: The conditional operator
14 =, arithmetic assignments
 
If two or more operators appear on the same precedence level, Java evaluates them from left to right. Therefore, in the expression w = x / y * z, Java first divides and then multiplies because the * and / operators both appear on the same precedence level so Java evaluates them from left to right as they appear in an expression. As always, you can override the left-to-right order with parentheses.

Summary

The goal of this chapter was to explain most of the Java operators. You saw how to specify literals, define variables, and then formulate expressions that use literals and variables with the extensive operators available to the Java language. Java includes mathematical operators as well as several comparison, logical, and bitwise operators. While some of these operators have side effects, such as the short-circuiting And and Or operators, most of the operators produce the results you would expect.

The operators taught in this chapter are not the only avenue you have as a Java programmer to perform calculations. The Java language's java.lang package contains numerous built-in mathematical class operations. Chapter 13 will explain how to take advantage of these advanced math language abilities.

In the next chapter, you will add to your Java language vocabulary. In a way, this chapter taught you Java's punctuation and the next chapter will teach you the words of the language. By combining this chapter's operators and the next chapter's commands, you'll be able to understand the purpose of majority of the Java code you'll ever see.

Here are the points this chapter covered:


Previous Page TOC Next Page

| Previous Chapter | Next Chapter |

| Table of Contents | Book Home Page |

| Que Home Page | Digital Bookshelf | Disclaimer |


To order books from QUE, call us at 800-716-0044 or 317-361-5400.

For comments or technical support for our books and software, select Talk to Us.

© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.