Tuesday 7 March 2017

Class Fundamentals & Declaring Objects - Java Tutorials

Class Fundamentals

Classes have been used since the beginning of this book. However, until now, only the most rudimentary form of a class has been used. The classes created in the preceding chapters primarily exist simply to encapsulate the main( ) method, which has been used to demonstrate the basics of the Java syntax. As you will see, classes are substantially more powerful than the limited ones presented so far.

Perhaps the most important thing to understand about a class is that it defines a new data type. Once defined, this new type can be used to create objects of that type. Thus, a class is a template for an object, and an object is an instance of a class. Because an object is an instance of a class, you will often see the two words object and instance used interchangeably.

The General Form of a Class

When you define a class, you declare its exact form and nature. You do this by specifying the data that it contains and the code that operates on that data. While very simple classes may contain only code or only data, most real-world classes contain both. As you will see, a class’ code defines the interface to its data.

A class is declared by use of the class keyword. The classes that have been used up to this point are actually very limited examples of its complete form. Classes can (and usually do) get much more complex. The general form of a class definition is shown here:

  class classname {
    type instance-variable1;
    type instance-variable2;
    // ...
    type instance-variableN;

    type methodname1(parameter-list) {
        // body of method
    }
    type methodname2(parameter-list) {
        // body of method
    }
      // ...
    type methodnameN(parameter-list) {
      // body of method
    }
  }

The data, or variables, defined within a class are called instance variables. The code is contained within methods. Collectively, the methods and variables defined within a class are called members of the class. In most classes, the instance variables are acted upon and accessed by the methods defined for that class. Thus, it is the methods that determine how a class’ data can be used.

Variables defined within a class are called instance variables because each instance of the class (that is, each object of the class) contains its own copy of these variables. Thus, the data for one object is separate and unique from the data for another. We will come back to this point shortly, but it is an important concept to learn early.

All methods have the same general form as main( ), which we have been using thus far. However, most methods will not be specified as static or public. Notice that the general form of a class does not specify a main( ) method. Java classes do not need to have a main( ) method. You only specify one if that class is the starting point for your program. Further, applets don’t require a main( ) method at all.

C++ programmers will notice that the class declaration and the implementation of the methods are stored in the same place and not defined separately. This sometimes makes for very large .java files, since any class must be entirely defined in a single source file. This design feature was built into Java because it was felt that in the long run, having specification, declaration, and implementation all in one place makes for code that is easier to maintain.

A Simple Class

Let’s begin our study of the class with a simple example. Here is a class called Box that defines three instance variables: width, height, and depth. Currently, Box does not contain any methods (but some will be added soon).

  class Box {
    double width;
    double height;
    double depth;
  }

As stated, a class defines a new type of data. In this case, the new data type is called Box. You will use this name to declare objects of type Box. It is important to remember that a class declaration only creates a template; it does not create an actual object. Thus, the preceding code does not cause any objects of type Box to come into existence.

To actually create a Box object, you will use a statement like the following:

  Box mybox = new Box(); // create a Box object called mybox

After this statement executes, mybox will be an instance of Box. Thus, it will have “physical” reality. For the moment, don’t worry about the details of this statement.

Again, each time you create an instance of a class, you are creating an object that contains its own copy of each instance variable defined by the class. Thus, every Box object will contain its own copies of the instance variables width, height, and depth. To access these variables, you will use the dot (.) operator. The dot operator links the name of the object with the name of an instance variable. For example, to assign the width variable of mybox the value 100, you would use the following statement:

  mybox.width = 100;

This statement tells the compiler to assign the copy of width that is contained within the mybox object the value of 100. In general, you use the dot operator to access both the instance variables and the methods within an object.

Here is a complete program that uses the Box class:

  /* A program that uses the Box class.

    Call this file BoxDemo.java
  */
  class Box {
    double width;
    double height;
    double depth;
  }

  // This class declares an object of type Box.
  class BoxDemo {
    public static void main(String args[]) {
      Box mybox = new Box();
      double vol;

      // assign values to mybox's instance variables
      mybox.width = 10;
      mybox.height = 20;
      mybox.depth = 15;

      // compute volume of box
      vol = mybox.width * mybox.height * mybox.depth;

      System.out.println("Volume is " + vol);
    }
  }

You should call the file that contains this program BoxDemo.java, because the main( ) method is in the class called BoxDemo, not the class called Box. When you compile this program, you will find that two .class files have been created, one for Box and one for BoxDemo. The Java compiler automatically puts each class into its own .class file. It is not necessary for both the Box and the BoxDemo class to actually be in the same source file. You could put each class in its own file, called Box.java and BoxDemo.java, respectively.

To run this program, you must execute BoxDemo.class. When you do, you will see the following output:

  Volume is 3000.0
  
As stated earlier, each object has its own copies of the instance variables. This means that if you have two Box objects, each has its own copy of depth, width, and height. It is important to understand that changes to the instance variables of one object have no effect on the instance variables of another. For example, the following program declares two Box objects:

  // This program declares two Box objects.
  class Box {
    double width;
    double height;
    double depth;
  }

  class BoxDemo2 {
    public static void main(String args[]) {
      Box mybox1 = new Box();
      Box mybox2 = new Box();
      double vol;

      // assign values to mybox1's instance variables
      mybox1.width = 10;
      mybox1.height = 20;
      mybox1.depth = 15;

      /* assign different values to mybox2's
         instance variables */
      mybox2.width = 3;
      mybox2.height = 6;
      mybox2.depth = 9;

      // compute volume of first box
      vol = mybox1.width * mybox1.height * mybox1.depth;
      System.out.println("Volume is " + vol);

      // compute volume of second box
      vol = mybox2.width * mybox2.height * mybox2.depth;
      System.out.println("Volume is " + vol);
    }
  }

The output produced by this program is shown here:

  Volume is 3000.0
  Volume is 162.0

As you can see, mybox1’s data is completely separate from the data contained in mybox2.




Declaring Objects

As just explained, when you create a class, you are creating a new data type. You can use this type to declare objects of that type. However, obtaining objects of a class is a two-step process. First, you must declare a variable of the class type. This variable does not define an object. Instead, it is simply a variable that can refer to an object. Second, you must acquire an actual, physical copy of the object and assign it to that variable. You can do this using the new operator. The new operator dynamically allocates (that is, allocates at run time) memory for an object and returns a reference to it. This reference is, more or less, the address in memory of the object allocated by new. This reference is then stored in the variable. Thus, in Java, all class objects must be dynamically allocated. Let’s look at the details of this procedure
.
In the preceding sample programs, a line similar to the following is used to declare an object of type Box:

  Box mybox = new Box();

This statement combines the two steps just described. It can be rewritten like this to show each step more clearly:

  Box mybox; // declare reference to object
  mybox = new Box(); // allocate a Box object

The first line declares mybox as a reference to an object of type Box. After this line executes, mybox contains the value null, which indicates that it does not yet point to an actual object. Any attempt to use mybox at this point will result in a compile-time error. The next line allocates an actual object and assigns a reference to it to mybox. After the second line executes, you can use mybox as if it were a Box object. But in reality, mybox simply holds the memory address of the actual Box object.

Those readers familiar with C/C++ have probably noticed that object references appear to be similar to pointers. This suspicion is, essentially, correct. An object reference is similar to a memory pointer. The main difference—and the key to Java’s safety—is that you cannot manipulate references as you can actual pointers. Thus, you cannot cause an object reference to point to an arbitrary memory location or manipulate it like an integer.

A Closer Look at new

As just explained, the new operator dynamically allocates memory for an object. It has
this general form:

  class-var = new classname( );

Here, class-var is a variable of the class type being created. The classname is the name of the class that is being instantiated. The class name followed by parentheses specifies the constructor for the class. A constructor defines what occurs when an object of a class is created. Constructors are an important part of all classes and have many significant attributes. Most real-world classes explicitly define their own constructors within their class definition. However, if no explicit constructor is specified, then Java will automatically supply a default constructor. This is the case with Box. For now, we will use the default constructor. Soon, you will see how to define your own constructors.

At this point, you might be wondering why you do not need to use new for such things as integers or characters. The answer is that Java’s simple types are not implemented as objects. Rather, they are implemented as “normal” variables. This is done in the interest of efficiency. As you will see, objects have many features and attributes that require Java to treat them differently than it treats the simple types. By not applying the same overhead to the simple types that applies to objects, Java can implement the simple types more efficiently. Later, you will see object versions of the simple types that are available for your use in those situations in which complete objects of these types are needed.

It is important to understand that new allocates memory for an object during run time. The advantage of this approach is that your program can create as many or as few objects as it needs during the execution of your program. However, since memory is finite, it is possible that new will not be able to allocate memory for an object because insufficient memory exists. If this happens, a run-time exception will occur. (You will learn how to handle this and other exceptions in Chapter 10.) For the sample programs in this book, you won’t need to worry about running out of memory, but you will need to consider this possibility in real-world programs that you write.

Let’s once again review the distinction between a class and an object. A class creates a new data type that can be used to create objects. That is, a class creates a logical framework that defines the relationship between its members. When you declare an object of a class, you are creating an instance of that class. Thus, a class is a logical construct. An object has physical reality. (That is, an object occupies space in memory.) It is important to keep this distinction clearly in mind.

Jump Statements - Java Tutorials

Java supports three jump statements: break, continue, and return. These statements transfer control to another part of your program. Each is examined here.

In addition to the jump statements discussed here, Java supports one other way that you can change your program’s flow of execution: through exception handling. Exception handling provides a structured method by which run-time errors can be trapped and handled by your program. It is supported by the keywords try, catch, throw, throws, and finally. In essence, the exception handling mechanism allows your program to perform a nonlocal branch. Since exception handling is a large topic, it is discussed in its own chapter, Chapter 10.


Using break

In Java, the break statement has three uses. First, as you have seen, it terminates a statement sequence in a switch statement. Second, it can be used to exit a loop. Third, it can be used as a “civilized” form of goto. The last two uses are explained here.

Using break to Exit a Loop

By using break, you can force immediate termination of a loop, bypassing the conditional expression and any remaining code in the body of the loop. When a break statement is encountered inside a loop, the loop is terminated and program control resumes at the next statement following the loop. Here is a simple example:

  // Using break to exit a loop.
  class BreakLoop {
    public static void main(String args[]) {
      for(int i=0; i<100; i++) {
        if(i == 10) break; // terminate loop if i is 10
        System.out.println("i: " + i);
      }
      System.out.println("Loop complete.");
    }
  }

This program generates the following output:

  i: 0
  i: 1
  i: 2
  i: 3
  i: 4
  i: 5
  i: 6
  i: 7
  i: 8
  i: 9
  Loop complete.

As you can see, although the for loop is designed to run from 0 to 99, the break statement causes it to terminate early, when i equals 10.

The break statement can be used with any of Java’s loops, including intentionally infinite loops. For example, here is the preceding program coded by use of a while loop. The output from this program is the same as just shown.

  // Using break to exit a while loop.
  class BreakLoop2 {
    public static void main(String args[]) {
      int i = 0;

      while(i < 100) {
        if(i == 10) break; // terminate loop if i is 10
        System.out.println("i: " + i);
        i++;
      }
      System.out.println("Loop complete.");
    }
  }

When used inside a set of nested loops, the break statement will only break out of the innermost loop. For example:

  // Using break with nested loops.
  class BreakLoop3 {
    public static void main(String args[]) {
      for(int i=0; i<3; i++) {
        System.out.print("Pass " + i + ": ");
        for(int j=0; j<100; j++) {
          if(j == 10) break; // terminate loop if j is 10
          System.out.print(j + " ");
        }
        System.out.println();
      }
      System.out.println("Loops complete.");
    }
  }

This program generates the following output:

  Pass 0: 0 1 2 3 4 5 6 7 8 9
  Pass 1: 0 1 2 3 4 5 6 7 8 9
  Pass 2: 0 1 2 3 4 5 6 7 8 9
  Loops complete.

As you can see, the break statement in the inner loop only causes termination of that loop. The outer loop is unaffected.

Here are two other points to remember about break. First, more than one break statement may appear in a loop. However, be careful. Too many break statements have the tendency to destructure your code. Second, the break that terminates a switch statement affects only that switch statement and not any enclosing loops.

break was not designed to provide the normal means by which a loop is terminated. The loop’s conditional expression serves this purpose. The break statement should be used to cancel a loop only when some sort of special situation occurs.

Using break as a Form of Goto

In addition to its uses with the switch statement and loops, the break statement can also be employed by itself to provide a “civilized” form of the goto statement. Java does not have a goto statement, because it provides a way to branch in an arbitrary and unstructured manner. This usually makes goto-ridden code hard to understand and hard to maintain. It also prohibits certain compiler optimizations. There are, however, a few places where the goto is a valuable and legitimate construct for flow control. For example, the goto can be useful when you are exiting from a deeply nested set of loops. To handle such situations, Java defines an expanded form of the break statement. By using this form of break, you can break out of one or more blocks of code. These blocks need not be part of a loop or a switch. They can be any block. Further, you can specify precisely where execution will resume, because this form of break works with a label. As you will see, break gives you the benefits of a goto without its problems. The general form of the labeled break statement is shown here:

  break label;

Here, label is the name of a label that identifies a block of code. When this form of break executes, control is transferred out of the named block of code. The labeled block of code must enclose the break statement, but it does not need to be the immediately enclosing block. This means that you can use a labeled break statement to exit from a set of nested blocks. But you cannot use break to transfer control to a block of code that does not enclose the break statement.

To name a block, put a label at the start of it. A label is any valid Java identifier followed by a colon. Once you have labeled a block, you can then use this label as the target of a break statement. Doing so causes execution to resume at the end of the labeled block. For example, the following program shows three nested blocks, each with its own label. The break statement causes execution to jump forward, past the end of the block labeled second, skipping the two println( ) statements.

  // Using break as a civilized form of goto.
  class Break {
    public static void main(String args[]) {
      boolean t = true;

      first: {
        second: {
          third: {
            System.out.println("Before the break.");
            if(t) break second; // break out of second block
            System.out.println("This won't execute");
          }
          System.out.println("This won't execute");
        }
        System.out.println("This is after second block.");
      }
    }
  }

Running this program generates the following output:

  Before the break.
  This is after second block.

One of the most common uses for a labeled break statement is to exit from nested loops. For example, in the following program, the outer loop executes only once:

  // Using break to exit from nested loops
  class BreakLoop4 {
    public static void main(String args[]) {
      outer: for(int i=0; i<3; i++) {
        System.out.print("Pass " + i + ": ");
        for(int j=0; j<100; j++) {
          if(j == 10) break outer; // exit both loops
          System.out.print(j + " ");
        }
        System.out.println("This will not print");
      }
      System.out.println("Loops complete.");
    }
  }

This program generates the following output:

Pass 0: 0 1 2 3 4 5 6 7 8 9 Loops complete.

As you can see, when the inner loop breaks to the outer loop, both loops have been terminated.

Keep in mind that you cannot break to any label which is not defined for an enclosing block. For example, the following program is invalid and will not compile:

  // This program contains an error.
  class BreakErr {
    public static void main(String args[]) {

      one: for(int i=0; i<3; i++) {
        System.out.print("Pass " + i + ": ");
      }

      for(int j=0; j<100; j++) {
        if(j == 10) break one; // WRONG
        System.out.print(j + " ");
      }
    }
  }

Since the loop labeled one does not enclose the break statement, it is not possible to transfer control to that block.

Using continue

Sometimes it is useful to force an early iteration of a loop. That is, you might want to continue running the loop, but stop processing the remainder of the code in its body for this particular iteration. This is, in effect, a goto just past the body of the loop, to the loop’s end. The continue statement performs such an action. In while and do-while loops, a continue statement causes control to be transferred directly to the conditional expression that controls the loop. In a for loop, control goes first to the iteration portion of the for statement and then to the conditional expression. For all three loops, any intermediate code is bypassed.

Here is an example program that uses continue to cause two numbers to be printed on each line:

  // Demonstrate continue.
  class Continue {
    public static void main(String args[]) {
      for(int i=0; i<10; i++) {
        System.out.print(i + " ");
        if (i%2 == 0) continue;
        System.out.println("");
      }
    }
  }

This code uses the % operator to check if i is even. If it is, the loop continues without printing a newline. Here is the output from this program:

  0 1
  2 3
  4 5
  6 7
  8 9

As with the break statement, continue may specify a label to describe which enclosing loop to continue. Here is an example program that uses continue to print a triangular multiplication table for 0 through 9.

  // Using continue with a label.
  class ContinueLabel {
    public static void main(String args[]) {
  outer: for (int i=0; i<10; i++) {
          for(int j=0; j<10; j++) {
            if(j > i) {
              System.out.println();
              continue outer;
            }
            System.out.print(" " + (i * j));
          }
        }
        System.out.println();
    }
  }

The continue statement in this example terminates the loop counting j and continues with the next iteration of the loop counting i. Here is the output of this program:

  0
  0 1
  0 2 4
  0 3 6 9
  0 4 8 12 16
  0 5 10 15 20 25
  0 6 12 18 24 30 36
  0 7 14 21 28 35 42 49
  0 8 16 24 32 40 48 56 64
  0 9 18 27 36 45 54 63 72 81

Good uses of continue are rare. One reason is that Java provides a rich set of loop statements which fit most applications. However, for those special circumstances in which early iteration is needed, the continue statement provides a structured way to accomplish it.

return

The last control statement is return. The return statement is used to explicitly return from a method. That is, it causes program control to transfer back to the caller of the method. As such, it is categorized as a jump statement. Although a full discussion of return must wait until methods are discussed in Chapter 7, a brief look at return is presented here.

At any time in a method the return statement can be used to cause execution to branch back to the caller of the method. Thus, the return statement immediately terminates the method in which it is executed. The following example illustrates this point. Here, return causes execution to return to the Java run-time system, since it is the run-time system that calls main( ).

  // Demonstrate return.
  class Return {
    public static void main(String args[]) {
      boolean t = true;

      System.out.println("Before the return.");

      if(t) return; // return to caller

      System.out.println("This won't execute.");
    }
  }

The output from this program is shown here:

  Before the return.

As you can see, the final println( ) statement is not executed. As soon as return is executed, control passes back to the caller.

One last point: In the preceding program, the if(t) statement is necessary. Without it, the Java compiler would flag an “unreachable code” error, because the compiler would know that the last println( ) statement would never be executed. To prevent this error, the if statement is used here to trick the compiler for the sake of this demonstration.

Iteration Statements - Java Tutorials

Java’s iteration statements are for, while, and do-while. These statements create what we commonly call loops. As you probably know, a loop repeatedly executes the same set of instructions until a termination condition is met. As you will see, Java has a loop to fit any programming need.

while

The while loop is Java’s most fundamental looping statement. It repeats a statement or block while its controlling expression is true. Here is its general form:

  while(condition) {
    // body of loop
  }

The condition can be any Boolean expression. The body of the loop will be executed as long as the conditional expression is true. When condition becomes false, control passes to the next line of code immediately following the loop. The curly braces are unnecessary if only a single statement is being repeated.

Here is a while loop that counts down from 10, printing exactly ten lines of “tick”:

  // Demonstrate the while loop.
  class While {
    public static void main(String args[]) {
      int n = 10;

      while(n > 0) {
        System.out.println("tick " + n);
        n--;
      }
    }
  }

When you run this program, it will “tick” ten times:

  tick 10
  tick 9
  tick 8
  tick 7
  tick 6
  tick 5
  tick 4
  tick 3
  tick 2
  tick 1

Since the while loop evaluates its conditional expression at the top of the loop, the body of the loop will not execute even once if the condition is false to begin with. For example, in the following fragment, the call to println( ) is never executed:

  int a = 10, b = 20;

  while(a > b)
    System.out.println("This will not be displayed");

The body of the while (or any other of Java’s loops) can be empty. This is because a null statement (one that consists only of a semicolon) is syntactically valid in Java. For example, consider the following program:

  // The target of a loop can be empty.
  class NoBody {
    public static void main(String args[]) {
      int i, j;

      i = 100;
      j = 200;

      // find midpoint between i and j
      while(++i < --j) ; // no body in this loop

      System.out.println("Midpoint is " + i);
    }
  }

This program finds the midpoint between i and j. It generates the following output:

  Midpoint is 150

Here is how the while loop works. The value of i is incremented, and the value of j is decremented. These values are then compared with one another. If the new value of i is still less than the new value of j, then the loop repeats. If i is equal to or greater than j, the loop stops. Upon exit from the loop, i will hold a value that is midway between the original values of i and j. (Of course, this procedure only works when i is less than j to begin with.) As you can see, there is no need for a loop body; all of the action occurs within the conditional expression, itself. In professionally written Java code, short loops are frequently coded without bodies when the controlling expression can handle all of the details itself.

do-while

As you just saw, if the conditional expression controlling a while loop is initially false, then the body of the loop will not be executed at all. However, sometimes it is desirable to execute the body of a while loop at least once, even if the conditional expression is false to begin with. In other words, there are times when you would like to test the termination expression at the end of the loop rather than at the beginning. Fortunately, Java supplies a loop that does just that: the do-while. The do-while loop always executes its body at least once, because its conditional expression is at the bottom of the loop. Its general form is

  do {
    // body of loop
  } while (condition);

Each iteration of the do-while loop first executes the body of the loop and then evaluates the conditional expression. If this expression is true, the loop will repeat. Otherwise, the loop terminates. As with all of Java’s loops, condition must be a Boolean expression.

Here is a reworked version of the “tick” program that demonstrates the do-while loop. It generates the same output as before.

  // Demonstrate the do-while loop.
  class DoWhile {
    public static void main(String args[]) {
      int n = 10;

      do {
        System.out.println("tick " + n);
        n--;
      } while(n > 0);
    }
  }

The loop in the preceding program, while technically correct, can be written more efficiently as follows:

  do {
    System.out.println("tick " + n);
  } while(--n > 0);

In this example, the expression (– –n > 0) combines the decrement of n and the test for zero into one expression. Here is how it works. First, the – –n statement executes, decrementing n and returning the new value of n. This value is then compared with zero. If it is greater than zero, the loop continues; otherwise it terminates.

The do-while loop is especially useful when you process a menu selection, because you will usually want the body of a menu loop to execute at least once. Consider the following program which implements a very simple help system for Java’s selection and iteration statements:

  // Using a do-while to process a menu selection
  class Menu {
    public static void main(String args[])
      throws java.io.IOException {
      char choice;

      do {
        System.out.println("Help on:");
        System.out.println(" 1. if");
        System.out.println(" 2. switch");
        System.out.println(" 3. while");
        System.out.println(" 4. do-while");
        System.out.println(" 5. for\n");
        System.out.println("Choose one:");
        choice = (char) System.in.read();
      } while( choice < '1' || choice > '5');

      System.out.println("\n");

      switch(choice) {
        case '1':
          System.out.println("The if:\n");
          System.out.println("if(condition) statement;");
          System.out.println("else statement;");
          break;
        case '2':
          System.out.println("The switch:\n");
          System.out.println("switch(expression) {");
          System.out.println("   case constant:");
          System.out.println("     statement sequence");
          System.out.println("   break;");
          System.out.println("   // ...");
          System.out.println("}");
          break;
        case '3':
          System.out.println("The while:\n");
          System.out.println("while(condition) statement;");
          break;
        case '4':
          System.out.println("The do-while:\n");
          System.out.println("do {");
          System.out.println("  statement;");
          System.out.println("} while (condition);");
          break;
        case '5':
          System.out.println("The for:\n");
          System.out.print("for(init; condition; iteration)");
          System.out.println(" statement;");
          break;
      }
    }
  }

Here is a sample run produced by this program:

  Help on:
    1. if
    2. switch
    3. while
    4. do-while
    5. for 
  Choose one:
  4
  The do-while:
  do {
    statement;
  } while (condition);

In the program, the do-while loop is used to verify that the user has entered a valid choice. If not, then the user is reprompted. Since the menu must be displayed at least once, the do-while is the perfect loop to accomplish this.

A few other points about this example: Notice that characters are read from the keyboard by calling System.in.read( ). This is one of Java’s console input functions. Although Java’s console I/O methods won’t be discussed in detail until Chapter 12, System.in.read( ) is used here to obtain the user’s choice. It reads characters from standard input (returned as integers, which is why the return value was cast to char). By default, standard input is line buffered, so you must press ENTER before any characters that you type will be sent to your program.

Java’s console input is quite limited and awkward to work with. Further, most real-world Java programs and applets will be graphical and window-based. For these reasons, not much use of console input has been made in this book. However, it is useful in this context. One other point: Because System.in.read( ) is being used, the program must specify the throws java.io.IOException clause. This line is necessary to handle input errors. It is part of Java’s exception handling features, which are discussed in Chapter 10.

for

You were introduced to a simple form of the for loop in Chapter 2. As you will see, it is a powerful and versatile construct. Here is the general form of the for statement:

  for(initialization; condition; iteration) {
    // body
  }

If only one statement is being repeated, there is no need for the curly braces.

The for loop operates as follows. When the loop first starts, the initialization portion of the loop is executed. Generally, this is an expression that sets the value of the loop control variable, which acts as a counter that controls the loop. It is important to understand that the initialization expression is only executed once. Next, condition is evaluated. This must be a Boolean expression. It usually tests the loop control variable against a target value. If this expression is true, then the body of the loop is executed. If it is false, the loop terminates. Next, the iteration portion of the loop is executed. This is usually an expression that increments or decrements the loop control variable. The loop then iterates, first evaluating the conditional expression, then executing the body of the loop, and then executing the iteration expression with each pass. This process repeats until the controlling expression is false.

Here is a version of the “tick” program that uses a for loop:

  // Demonstrate the for loop.
  class ForTick {
    public static void main(String args[]) {
      int n;

      for(n=10; n>0; n--)
        System.out.println("tick " + n);
    }
  }


Declaring Loop Control Variables Inside the for Loop

Often the variable that controls a for loop is only needed for the purposes of the loop and is not used elsewhere. When this is the case, it is possible to declare the variable inside the initialization portion of the for. For example, here is the preceding program recoded so that the loop control variable n is declared as an int inside the for:

  // Declare a loop control variable inside the for.
  class ForTick {
    public static void main(String args[]) {

      // here, n is declared inside of the for loop
      for(int n=10; n>0; n--)
        System.out.println("tick " + n);
    }
  }

When you declare a variable inside a for loop, there is one important point to remember: the scope of that variable ends when the for statement does. (That is, the scope of the variable is limited to the for loop.) Outside the for loop, the variable will cease to exist. If you need to use the loop control variable elsewhere in your program, you will not be able to declare it inside the for loop.

When the loop control variable will not be needed elsewhere, most Java programmers declare it inside the for. For example, here is a simple program that tests for prime numbers. Notice that the loop control variable, i, is declared inside the for since it is not needed elsewhere.

  // Test for primes.
  class FindPrime {
    public static void main(String args[]) {
      int num;
      boolean isPrime = true;

      num = 14;
      for(int i=2; i <= num/2; i++) {
        if((num % i) == 0) {
          isPrime = false;
          break;
        }
      }
      if(isPrime) System.out.println("Prime");
      else System.out.println("Not Prime");
    }
  }


Using the Comma

There will be times when you will want to include more than one statement in the initialization and iteration portions of the for loop. For example, consider the loop in the following program:

  class Sample {
    public static void main(String args[]) {
      int a, b;

      b = 4;
      for(a=1; a<b; a++) {
        System.out.println("a = " + a);
        System.out.println("b = " + b);
        b--;
      }
    }
  }

As you can see, the loop is controlled by the interaction of two variables. Since the loop is governed by two variables, it would be useful if both could be included in the for statement, itself, instead of b being handled manually. Fortunately, Java provides a way to accomplish this. To allow two or more variables to control a for loop, Java permits you to include multiple statements in both the initialization and iteration portions of the for. Each statement is separated from the next by a comma.

Using the comma, the preceding for loop can be more efficiently coded as shown here:

  // Using the comma.
  class Comma {
    public static void main(String args[]) {
      int a, b;

      for(a=1, b=4; a<b; a++, b--) {
        System.out.println("a = " + a);
        System.out.println("b = " + b);
      }
    }
  }

In this example, the initialization portion sets the values of both a and b. The two comma-separated statements in the iteration portion are executed each time the loop repeats. The program generates the following output:

  a = 1
  b = 4
  a = 2
  b = 3

If you are familiar with C/C++, then you know that in those languages the comma is an operator that can be used in any valid expression. However, this is not the case with Java. In Java, the comma is a separator that applies only to the for loop. 

Some for Loop Variations

The for loop supports a number of variations that increase its power and applicability. The reason it is so flexible is that its three parts, the initialization, the conditional test, and the iteration, do not need to be used for only those purposes. In fact, the three sections of the for can be used for any purpose you desire. Let’s look at some examples.

One of the most common variations involves the conditional expression. Specifically, this expression does not need to test the loop control variable against some target value. In fact, the condition controlling the for can be any Boolean expression. For example, consider the following fragment:

  boolean done = false;

  for(int i=1; !done; i++) {
    // ...
    if(interrupted()) done = true;
  }

In this example, the for loop continues to run until the boolean variable done is set to true. It does not test the value of i.

Here is another interesting for loop variation. Either the initialization or the iteration expression or both may be absent, as in this next program:

  // Parts of the for loop can be empty.
  class ForVar {
    public static void main(String args[]) {
      int i;
      boolean done = false;

      i = 0;
      for( ; !done; ) {
        System.out.println("i is " + i);
        if(i == 10) done = true;
        i++;
      }
    }
  }

Here, the initialization and iteration expressions have been moved out of the for. Thus, parts of the for are empty. While this is of no value in this simple example—indeed, it would be considered quite poor style—there can be times when this type of approach makes sense. For example, if the initial condition is set through a complex expression elsewhere in the program or if the loop control variable changes in a nonsequential manner determined by actions that occur within the body of the loop, it may be appropriate to leave these parts of the for empty.

Here is one more for loop variation. You can intentionally create an infinite loop (a loop that never terminates) if you leave all three parts of the for empty. For example:

  for( ; ; ) {
    // ...
  }

This loop will run forever, because there is no condition under which it will terminate. Although there are some programs, such as operating system command processors, that require an infinite loop, most “infinite loops” are really just loops with special termination requirements. As you will soon see, there is a way to terminate a loop—even an infinite loop like the one shown—that does not make use of the normal loop conditional expression.

Nested Loops

Like all other programming languages, Java allows loops to be nested. That is, one loop may be inside another. For example, here is a program that nests for loops:

  // Loops may be nested.
  class Nested {
    public static void main(String args[]) {
      int i, j;

      for(i=0; i<10; i++) {
        for(j=i; j<10; j++)
          System.out.print(".");
        System.out.println();
      }
    }
  }

The output produced by this program is shown here:

..........
.........
........
.......
......
.....
....
...
..
.