Copyright ©1996, Que Corporation. All rights reserved. No part of this book may be used or reproduced in any form or by any means, or stored in a database or retrieval system without prior written permission of the publisher except in the case of brief quotations embodied in critical articles and reviews. Making copies of any part of this book for any purpose other than your own personal use is a violation of United States copyright laws. For information, address Que Corporation, 201 West 103rd Street, Indianapolis, IN 46290 or at support@mcp .com.

Notice: This material is excerpted from Special Edition Using Java, ISBN: 0-7897-0604-0. The electronic version of this material has not been through the final proof reading stage that the book goes through before being published in printed form. Some errors may exist here that are corrected before the book is published. This material is provided "as is" without any warranty of any kind.

Chapter 13 - Statements in Depth

by Jay Cross

Statements in Java are like sentences in human languages. In a way, the demand that things expressed in a computer language be very precise and error free makes it more difficult to use a computer language than a human one. On the other hand, in a computer language, there is generally only one tense (the imperative), as opposed to the thirty-eight or so that make up the Romance languages. There are only a hundred or so predefined keywords and other tokens. Even throwing in all the commercially available classes, and their public methods still leaves Java much smaller than the hundred thousand to half a million words that English has incorporated. Java's keywords, operators, classes, and methods are very seldom as heavily overloaded as words in human language. It is always possible to determine which definition of a term is intended in Java statements.

Expressing something is more than just stringing terms together. In human languages or computer languages you must make statements, and statements have specific forms. The forms of Java statements are described in the following sections.

In this chapter about Java statements you will learn:

Blocks and Statements

Methods, and Static initializers in Java are defined by blocks of statements. A block of statements is a series of statements enclosed within curly-braces ({}). When a statement's form calls for a statement or substatement as a part, a block may be inserted in the substatement's place.

A block of statements has its own local scope for the statements within it. This means that local variables may be declared within this block, which are unavailable outside the block, and whose very existence is extinguished when the block has completed execution. (In most systems, they are stored on a stack.)

There is nothing in the definition of Java that prevents the programmer from breaking code into blocks even though they are not specifically called for, but it is seldom done. The following code fragment demonstrates this legal but seldom done technique:

String Batter;
Short Inning, Out, Strikes;
Batsman Casey;                         // Object of class Batsman.
...
If ((Inning == 9) && (Out==2) && (Batter.equals("Casey"))) {
     Casey.manner("ease");
     Casey.bearing("pride");
     {                                   // Begins new block for no reason.
          int OnlyExistsInThisBlock = 1;
          Casey.face("smile");
          Casey.hat("lightly doff");
     }                                   // Ends superfluous blocking.
     
}

Notice that this fragment contains two complete blocks. One is the substatement of the If statement, and the other is the unneeded block, which contains the unused integer OnlyExistsInThisBlock. Experienced programmers know that if there are two blocks, A and B, A cannot contain part of B unless A contains all of B. Syntactically this is because the curly-braces ({}) are always interpereted in a nested fashion.

Empty Statements

It is legal to create an empty statement in Java. This is a statement that holds a place in the code but does nothing. Some programmers find this handy for holding labels or for some other trick that may make program maintenance a bit easier. To the compiler, it looks like an extra semicolon. The following code fragment shows an four empty statements together.

while (strike++ < 2) {
     Casey.RubHands("dirt");
     Casey.WipeHands("shirt");
     ;;;;                    // four empty statement here for emphasis.
     Casey.WatchPitch();
}

Labeled Statements

Any statement in Java can have a label. The actual label has the same properties as any other identifier; it cannot have the same name as a keyword or already declared local identifier. If it has the same name as a variable, method, or type name that is available to this block, then within that block, the new label takes precedence and that outside variable, method, or type is hidden. It has the scope of the current block. The label is followed by a colon.

Labels are only used by the break and continue Jump statements described below. The details of this use are given in the section entitled Jump Statements.

An example of labeled statements appears in the following code fragment:

writhing:
        Pitcher.GrindsBall("Hip");
        Casey.eye("Defiance Gleams");
        Casey.lip("Curling Sneer");
pitch:  while (strike++ < 2) {
                if (strike < 2) continue pitch;
                break writhing;               
        }

The statement, writhing, is simple labeling of an expression statement, in this case, a method call from a rather complicated object called Pitcher. The statement pitch is labeling an iteration statement (while). This label is used as a parameter for the continue statement.

Declarations

In short, a declaration statement defines a variable, whether class, interface, array, object, or primitive type. The form of such a statements depend on which of the five types is being declared.

Class Declaration

A class declaration is composed of the following six parts which are put together in this order.

Classes and their declarations are described more fully in Chapter 11.

Interface Declaration

An interface declaration is composed of the following five parts, which are put together in this order.

Interfaces and their declarations are described more fully in Chapter 12

Array Declaration

Array declarations are composed of the following parts.

Arrays and their declarations are described more fully in Chapter 12.

Object Declaration

When an object is declared, a reference is created for it. That reference only points to an object if an object is initialized or assigned to that reference. An object declaration has the following parts:

Objects and their declarations are described more fully in Chapter 11.

Primitive Type Declaration

When a variable of a primative type is declared, storage space for that variable is created. If there is no value assigned to it by an explicit initialization clause, it takes on the default value which is zero for the numeric and char types, and false for booleans. A declaration for a primative type is composed of the following parts:

Primitive types and their declarations are described more fully in Chapter 10.

Expression Statements

The Java Language Specification lists seven kinds of Expression statements. They are Assignment, Pre-increment, Pre-decrement, Post-Increment, Post-decrement, Method call, and Allocation Expression.

All of the Expression statements are terminated with a semicolon.

All side effects of an expression statement will have taken effect before the next statement is executed.

A Java Assignment statement may have an expression on the right side of the assignment operator (=). This expression can be any of the seven types of expression statements. Only the right side of such an assignment may be cast.

Note that even though Java is fairly strongly typed, it is legal for the return value of a nonvoid method to be called without assignment (implicitly casting it as void).

The following code fragment gives a sample of each of the seven types of expression statements:

Inning = 9;                     // Assignment: put the value 9 in Inning.
++strike;                       // PreIncrement: adds 1 to strike before
                                //         the statement is evaluated.
--strike;                       // Predecrement: subtracts 1 from strike
                                //        before the statement is evaluated.
pitch++;                        // PostIncrement: adds 1 to pitch after
                                //        the statement is evaluated.
pitch--;                        // Postdecrement: subtracts 1 from pitch
                                //        after the statement is evaluated.
Umpire.Said("Strike One");      // Method Call: Invokes the method 'Said'
                                //         for the object Umpire, with 
                                //        "Strike One" as a parameter.
byte Score[][];
Score = new byte[2][12];        // Allocation Expression: allocates space
                                //        for the array 'Score'.

An expression statement may be considerably more complex than those in the preceding fragment, and parentheses may be used to affect the order in which the various subexpressions are evaluated.

More details about the use of the allocation statement
for creating space for instances of arrays and objects can be
found in Chapter 10 and Chapter 11.

Selection Statements

Java supports three types of selection statements: if, if-else, and switch. These are very similar to the statementsof the same type found in C and C++.

if statements

An if statement tests a Boolean variable or expression to determine whether to execute a statement or block of statements. If the Boolean is true, the block is executed; if not, program control passes to the next statement after the block. An example of an if statement is shown in the following code fragment:

if (umpire.says.equals("Strike two")){  //equals method returns boolean
     Croud.cry("Fraud");                        // method call
     Strike++;                                  // last statement in if block.
}
Casey.face("Christian charity");                // 1st statement after if block.

In this example if the object umpire's method "says" returns a string "Strike two", then the block will be executed, and control is passed to the next statement. If the string returned says something else (such as "Strike one", "Strike too", "sTRIKE TWO", or "Play Ball") then the next statement executed will be the call to the face method for the object Casey.

if-else statements

An if-else statement is very similar to the if statement, except that it has an else clause. An else clause passes control to a statement or block if the Boolean evaluated in the if portion of the statement was false. An example of an if-else statement appears in the following code fragment:

if (strike != 2) 
     Casey.lip("Curling Sneer");                // single substatement (could have been a block)
else {
     Casey.teeth("Clenched in hate");           // block of substatements (could have been single)
     Casey.bat.pound("Plate");
}

In this example, the if clause has one statement. The else clause controls a block of two statements. Experienced programmers will recognize that the one substatement of the if clause could have been an if statement, which would lead to some ambiguity as to which if the else was attached to. In the absence of curly braces, Java resolves this ambiguity by connecting the else with the next most recent "elseless" if statement in the block. If there are none, a compile-time error is generated.

Switch Statements

A switch statement permits passing control to one of many statements within its block of substatements, depending on the value of the expression in the statement. Control is passed to the first statement following a case label with the same value as the expression. If there are none, control passes to the first statement after the "default" label. If there is no default label, control passes to the first statement after the switch block. The switch expression and case label constants must all evaluate to either byte, short, char, or int. No two case labels in the same switch block can have the same value.

Labels do not affect the control flow. Control continues on through one of these labels as if it weren't there. As a consequence, multiple labels can precede the same line of code. As a general practice, programmers put a break statement at the end of each labeled section of code to prevent executing more than one set of statements.

An example of the switch statement is included in the following code fragment:

switch (strike) {
case 0:
case 1:
     Casey.lip("Curling Sneer");
     break;
case 2:
     Casey.teeth("Clenched in hate");
     Casey.bat.pound("Plate");
     break;
default:
     System.out.println("Strike out of range");
}

In this example, we assume that strike is a compatible integer type (e.g. int). Control passes to the correct line, depending on the value of strike. If strike doesn't have one of the values it should have, a programmer-defined error message is printed.

switch statements are much like the statements of the same name in C and C++.

Iteration Statements

Programmers use iteration statements to control sequences of statements that are repeated according to run-time conditions.

Java supports three types of iteration statements: while, do, and for. These are very similar to the statements of the same type found in C and C++, with the exception that continue and break statements in Java have optional parameters which can change their behavior (compared with C and C++, where these statements have no parameters) within the substatement blocks. You will read more about the use of parameters in break and continue statements later in this chapter.

while Statements

The while statement tests a boolean variable or expression, and if it is true, executes the sub-statement or block repeatedly until it is false. When the variable or expression is false, control is passed to the next statement after the while statement's sub-statement or block. An example of a while statement appears in the following code fragment.

while (Casey.RoundingTheBasepads==true) {
     Crowd.cry("Hooray for Casey");
}

In this example, it is clear that the expression might not be true initially, and if not, the block in the sub-statement will never be executed. If it is true, this block of code is executed repeatedly until it is not true, or until a jump statement (not appearing in this code fragment) is executed, and passes control to a statement outside the loop.

do Statements

The do statement is much like the while statement. In fact, it has a while clause at the end. Like the while statement above, the expression in the while statement must be a boolean. The primary reason that a programmer chooses to use a do statement instead of a while statement is if the block of code needs to be executed at least once, no matter what.

do {
     Crowd.cry("Kill the Umpire!");
} while (umpire.says.equals("Strike two"));

In this example, the method Crowd.cry is invoked at least once no matter what. But as long as the umpire.says method returns the string "Strike two", the Crowd.cry method is called over and over again.

for Statements

for statements are the most complicated of the three iteration statements. Yet for statements are complicated by some useful features, which make them the most used of the three. The for statement is composed of:

An example of a for loop appears in the following code fragment:

for (int ball=0, int strike=0; (ball<4) && (strike<3); System.out.println("Here's the pitch"), Pitcher.pitch()) {
     if (Ump.CallPitch.equals("Strike")) {
          strike++;
          System.out.println("Strike " + strike);
     }
     else if (Ump.CallPitch.equals("Ball")) {
          ball++;
          System.out.println("Ball " + ball);
     }
     else     
          break;
}

In this example, the initialization clause declares and initializes two variables, ball and strike. The test clause returns false if either ball four or strike three are called, and the iteration clause calls println, and the pitch method for the object Pitcher.

The loop itself prints the ball or strike number, and goes back to the top of the loop. If Ump.CallPitch does not return a ball or strike, the loop is exited prematurely. It is beyond the scope of this fragment to account for foul balls and do-overs.

Jump Statements

Java has four kinds of Jump statements : break, continue, return, and throw.

break Statements

The substatement blocks of loops and switch statements can be broken out of by use of the break statement. An unlabeled break statement passes control to the next line after the current (inner-most) iteration (while, do, or for loop) or switch statement. With a label, control may be passed to a statement with that label in the current method. If there is a finally clause of a currently open try statement within the loop, that clause will be executed before control is passed.

You will find a description of the try, catch, and finally statements below, with a more detailed explanation of their use in chapters that explore writing applets.

Those who mock good programming practices will be pleased to note that the labeled break statement can be made to act as the expunged-from-Java goto statement.

The code fragments in this chapter contain several examples of unlabeled break statements.

continue statements

A continue statement may only appear within the sub-statement block of an iteration statement (while, do or for). The effect of the unlabeled continue statement is to skip the remainder of the statements in the innermost iteration statement's block, and go on to the next pass through the loop. The label parameter permits the programmer to choose which level of nested iteration statements to continue with.

If there is a finally clause for a currently open try statement within the indicated level of nesting, that clause will be executed before control is passed.

return statements

A return statement passes control to the caller of the method, constructor, or static initializer containing the return statement. If the return statement is in a method that is not declared void, it may have a parameter of the same type as the method.

If there is a finally clause for a currently open try statement, that clause will be executed before control is passed.

throw statements

A throw statement signals a run-time exception. It takes an argument which is an object. This object is normally of a subclass of Exception.

When the throw statement is encountered, execution is suspended. Levels of enclosing statements (statements with substatements or blocks) are closed until a catch clause is found with a formal argument which is a superclass of the type in the throw statement.

The finally clause of any try statements are executed along the way as they are encountered.

More details about throw statements are available in Chapter 18.

Synchronization Statements

Java has a keyword synchronized which some sources list as a type of statement, and others list as a modifier in declarations. It is part of Java being multithreaded, and is covered in more detail in chapters 23, 24, and 25.

Guarding Statements

Java has three kinds of statements called Guarding Statements. These are try, catch, and finally. These statements are used to set up exception handling around a method which could possibly generate an exception. To some limited degree they are like the switch-case-default statements mentioned above. In this analogy the try statement is like the switch statement. Instead of an integer parameter, the try statement takes a block of code. If an exception occurs which is not handled by some inner try-catch-finally type handler, then execution of the block is suspended, and control is passed to the catch statement with the right object type as an argument.

The catch statements have the exception handler objects as arguments.

The finally statements permit wrapping up essential things (such as closing files) before execution is halted.

Unreachable Statements

It is possible to write a method that has lines of code which can never be reached. Lines between an unconditional return statement, and the next label, or end of the block are the clearest example. It can be written, but it can't be compiled. A compile-time error is generated.

QUE Home Page

For technical support for our books and software contact support@mcp.com

Copyright ©1996, Que Corporation