JTF > Tutorial > Introduction

Chapter 1
Introduction to the JTF Packages


Since its release in 1995, the Java programming language has become increasingly important as a vehicle for teaching introductory programming. Java has many significant advantages over earlier teaching languages and enables students to write exciting programs that capture their interest and imagination. At the same time, Java is far more sophisticated than languages that have traditionally filled that role, such as BASIC and Pascal. The complexity that comes with that sophistication can be a significant barrier to both teachers and students as they try to understand the structure of the language.

  In early 2004, the ACM created the Java Task Force (JTF) and assigned it the following charge:

To review the Java language, APIs, and tools from the perspective of introductory computing education and to develop a stable collection of pedagogical resources that will make it easier to teach Java to first-year computing students without having those students overwhelmed by its complexity.

After two preliminary releases in February 2005 and February 2006, the JTF released its final report in July 2006.

  This tutorial is designed to give instructors a gentle introduction into how to use the JTF materials in the context of an introductory programming course. As a tutorial, this document does not attempt to cover every detail of the various JTF packages, nor does it try to defend the decisions that went into the overall design. The complete description of the packages can be found in the online javadoc; a review of the design is available in the Java Task Force Rationale document.

1.1 Getting started

In their classic textbook The C Programming Language, Brian Kernighan and Dennis Ritchie offered the following observation at the beginning of Chapter 1:

The only way to learn a new programming language is by writing programs in it. The first program to write is the same for all languages:

   Print the words
     hello, world

This is the big hurdle; to leap over it you have to be able to create the program text somewhere, compile it successfully, load it, run it, and find out where the output went. With these mechanical details mastered, everything else is comparatively easy.

Even though C has given way to Java and our expectations of what constitutes an interesting first program have changed, the wisdom of getting the mechanical details out of the way remains as applicable as ever. During the review process for the JTF packages, the most common questions we received were from users who were unsure how to compile and run programs that made use of any libraries beyond the standard classes supplied with the Java distribution. Once that hurdle was cleared, using the JTF packages seemed to be straightforward.

Downloading the “hello, world” programs

The moral of the story, therefore, is that it is essential to get a simple program working before you move on to more complex examples. Taking our inspiration from Kernighan and Ritchie, our first example will be a simple program that displays the “hello, world” message. You can download the code for this program—along with a copy of the acm.jar library and a couple of more advanced versions of the program—from the following web address:

http://www.acm.org/jtf/downloads/Hello.zip

Please take a moment to download the Hello.zip file and unzip it on your computer. If you are reading this tutorial online, you should be able simply to click on the link. Most browser programs will automatically download and unzip the code with no further interaction on your part. When you have done so, you should see a directory named Hello that contains the following four files: HelloConsole.java, HelloDialog.java, HelloGraphics.java, and acm.jar. The first three are Java program files, and the last one is a library file that contains the compiled code for the JTF packages.

Figure 1-1. Simple program to display “hello, world” on the screen
/*
 * File: HelloConsole.java
 * -----------------------
 * This program displays the message "hello, world" and is inspired
 * by the first program "The C Programming Language" by Brian
 * Kernighan and Dennis Ritchie.  This version displays its message
 * using a console window.
 */
 
import acm.program.*;
 
public class HelloConsole extends ConsoleProgram {
 
   public void run() {
      println("hello, world");
   }
 
/* Standard Java entry point */
/* This method can be eliminated in most Java environments */
   public static void main(String[] args) {
      new HelloConsole().start(args);
   }
} 

  Once you have successfully downloaded these files, your next step is to compile and run the HelloConsole program, which is the simplest of the examples. The code for this version of the program appears in Figure 1-1. If you are using the traditional command-line interface supplied with Sun’s Java Development Kit, this process requires two steps. The first step is to compile the HelloConsole.java file by issuing the command

 

javac -classpath acm.jar HelloConsole.java

You can then run the program by invoking the command

 

java -cp .:acm.jar HelloConsole

On Windows platforms, the colon in the classpath must be replaced with a semicolon (;). Note that the acm.jar file must be specified as part of both the compilation and execution steps.

  If everything is working, the computer should pop up a console window that looks something like this:

  If you are using one of the many Integrated Development Environments (IDEs) available for Java—such as Microsoft Visual StudioTM, Metrowerks CodeWarriorTM, or the open-source Eclipse system—you will need to ensure that the acm.jar file is included as part of the classpath, which is the list of directories and JAR files that Java searches to find class definitions that are not part of the source files. The procedure for doing so varies from system to system. Please check the documentation for your own IDE to see how one goes about specifying the classpath.

Eliminating the static main method

As soon as you have the HelloConsole program working, it is useful to try one additional experiment. If you look at the code in Figure 1-1, you will see that there is a main method at the end of the class definition. As the comment indicates, it is possible to eliminate this method in many Java environments, but not all. Open the HelloConsole.java file in an editor, delete the main method and its associated comments, and then see if you can still compile and run the program. If so, you will be able to write shorter programs that will be much easier for novices to understand. If not, you will need to tell your students to include a standardized main method in their programs that always looks like

 

public static void main(String[] args) {
   new MainClass().start(args);
}

where MainClass is the name of the main class.

  The examples available on the JTF web site include a static main method to ensure that these programs will run in as many environments as possible. For clarity of presentation, however, the programs in the remainder of this tutorial eliminate the main method to focus attention on the more substantive parts of these examples. The programs instead begin with a run method, which is called after the runtime libraries have created the necessary windows and arranged them on the screen.

Making the programs a little more interesting

Although getting the HelloConsole program working is a good first step, it isn’t a particularly exciting example. If nothing else, the program seems terribly out of date. While printing a message on the console may have been a reasonable example in the 1970s, students today are used to much more sophisticated programs, with fancy graphics and interactive dialogs. Surely a modern object-oriented language like Java can do better than duplicating the kind of program students wrote a generation ago.

  That’s where the other two programs that you downloaded as part of the Hello.zip file come in. If you compile and run the HelloDialog.java program in precisely the same way that you ran HelloConsole.java, the "hello, world" message won’t appear in a console window. In fact, the program doesn’t create a program frame at all. Instead the prorgam pops up an interactive dialog box that looks something like this, although the precise format of the display will vary depending on what operating system you are using and what “look and feel” it defines for Java applications:

The HelloGraphics.java file uses the facilities of the acm.graphics package to display the message in large, friendly letters across the window:

  The code for each of these programs is similar in certain respects to that used in HelloConsole. The HelloDialog program is almost exactly the same. Other than changes in the comments, the only difference is the header line for the class, which now looks like this:

 

public class HelloDialog extends DialogProgram

The body of the class is exactly the same. The only difference—which is sufficient to cause the change in behavior—is that this version extends DialogProgram instead of ConsoleProgram.

  The code for HelloGraphics appears in Figure 1-2. The details of the program are not important at this point, and will be covered in Chapter 2. Even so, the basic idea is likely to be clear, even if you could not have generated the code as it stands. The first line creates a GLabel object with the message text, the second line gives it a larger font, and the last three lines take care of adding the label so that it is centered in the window. What is important to notice is that the HelloGraphics class extends GraphicsProgram, which is yet another category of program. These three classes—ConsoleProgram, DialogProgram, and GraphicsProgram are the building blocks for Java applications built using the acm.program package, which is introduced in the following section.

Figure 1-2. Program to display “hello, world” graphically [applet]
/*
 * File: HelloGraphics.java
 * ------------------------ 
 * This program displays the message "hello, world" and is inspired
 * by the first program "The C Programming Language" by Brian
 * Kernighan and Dennis Ritchie.  This version displays the message
 * graphically.
 */
 
import acm.graphics.*;
import acm.program.*;
 
public class HelloGraphics extends GraphicsProgram {
 
   public void run() {
      GLabel label = new GLabel("hello, world");
      label.setFont("SansSerif-100");
      double x = (getWidth() - label.getWidth()) / 2;
      double y = (getHeight() + label.getAscent()) / 2;
      add(label, x, y);
   }
 
} 

1.2 The Program class hierarchy

Each of the applications contained in the Hello.zip file represents a simple, paradigmatic example of one of three classes defined in the package called acm.program. The classes for the various versions of the "hello, world" program—taken together with the classes defined in the acm.program package—form the class hierarchy shown in Figure 1-3. As the diagram shows, each of the example applications is a subclass of a specific program type: HelloConsole is a subclass of ConsoleProgram, HelloDialog is a subclass of DialogProgram, and HelloGraphics is a subclass of GraphicsProgram. Each of these classes is a subclass of a more general Program class, which is in turn a subclass of Swing’s JApplet class.

Figure 1-3. The Program class hierarchy

  The program class hierarchy in Figure 1-3 provides a straightforward introduction to the ideas of subclassing and inheritance that students seem to find compelling. After all, the word program has the intuitive meaning of some kind of application that can be executed on a computer. It is clear, moreover, that there are different kinds of programs, which provides a motivation for subclassing. A particular program running on a machine—HelloConsole, for example—is an instance of a ConsoleProgram, but it is also clearly an instance of a more generic Program class. This inheritance structure therefore exemplifies the is-a relationship between a class and its superclass in a seemingly natural way.

  Using the Program class offers several advantages beyond the pedagogical one of serving as an archetype for class hierarchies:

Behavior common to all Program classes

Sitting as it does at the root of the program hierarchy, the Program class defines the behavior that all of its subclasses share, and it is therefore important to understand something of how the Program class works before moving on to its individual subclasses. The most important feature of the Program class is that it standardizes the process of program startup in a way that unifies the traditionally disparate models of applications and applets. The idea is that a program should work the same way if you run it as an application or as an applet in the context of a web browser. To achieve this goal, the Program class automatically executes several of the operations that a browser performs when running an applet. Thus, no matter whether you run a program as a standalone application or view it as an applet running inside a web browser, the startup process consists of the following steps:

  1. Create a new instance of the main class.
  2. Create a frame in which to run the program.
  3. Install components in the frame as required by the program subclass. A ConsoleProgram, for example, installs a console in the frame; a GraphicsProgram, by contrast, installs a graphical canvas.
  4. Call the program’s init method to perform any application-specific initializion.
  5. Ensure that the frame layout is up to date by calling validate.
  6. Call the run method using a new thread of control.

For the most part, these steps are entirely automatic, and the student doesn’t need to be aware of the details. From the student’s perspective, the essential step in getting a program running is defining a run method that contains the code, as illustrated by each of the three implementations of the "hello, world" program. The code for each run method depends to some extent on the specific subclass, so that the code for a ConsoleProgram will include method calls for interacting with a console while a GraphicsProgram will include calls for displaying graphical objects on a canvas. Despite these differences, the startup operations for every program subclass remain the same.

  The sections that follow offer a quick introduction to the ConsoleProgram, DialogProgram, and GraphicsProgram classes. For a more complete description of the methods available in each class, please see the javadoc documentation.

The ConsoleProgram class

A ConsoleProgram begins by creating a console window and installing it in the program frame. The code for the ConsoleProgram then communicates with the user through calls to methods that are passed on to the console, such as the

 

println("hello, world");

you saw in the the HelloConsole example.

  Although the ConsoleProgram class exports much larger set of input and output methods as defined by the IOModel interface in the acm.io package, you can easily get started using only the methods listed in Figure 1-4. This set includes the familiar print and println methods provided by the classes in the java.io package along with a set of methods like readInt, readDouble, and readLine for reading input of various types.

Figure 1-4. Useful methods in the ConsoleProgram class
Output methods
 
void print(any value)
  Writes the value to the console with no terminating newline.
void println(any value)
  Writes the value to the console followed by a newline.
void println()
  Returns the cursor on the console to the beginning of the next line.
void showErrorMessage(String msg)
  Displays an error message on the console, which appears in red.

 Input methods
 
String readLine(String prompt)
  Reads and returns a line of text from the console without the terminating newline.
int readInt(String prompt)
  Reads and returns an int value from the console.
double readDouble(String prompt)
  Reads and returns an double value from the console.

 Additional methods
 
void setFont(Font font)  or  void setFont(String str)
  Sets the overall font for the console, which may also be specified as a string.
void clear()
  Clears the console screen.

  The code for the Add2Console program in Figure 1-5 offers an extremely simple illustration of how to use the ConsoleProgram class: a program that reads in two integers from the user and prints their sum. A sample run of the Add2Console program might look like this:

Figure 1-5. Program to add two numbers entered on the console [applet]
/*
 * File: Add2Console.java
 * ---------------------- 
 * This program adds two numbers and prints their sum.  Because
 * this version is a ConsoleProgram, the input and output appear
 * on the console.
 */
 
import acm.program.*;
 
public class Add2Console extends ConsoleProgram {
 
   public void run() {
      println("This program adds two numbers.");
      int n1 = readInt("Enter n1: ");
      int n2 = readInt("Enter n2: ");
      int total = n1 + n2;
      println("The total is " + total + ".");
   }
 
} 

  Given that the ConsoleProgram class derives its inspiration from the classical paradigm of text-based, synchronous interaction, using this model is generally quite straightforward for those who learned programming in that domain. If you use the Add2Console program as a template, you can easily write new versions of any of the traditional programs from the days of Pascal and C when consoles represented the primary style of interaction. Even though the underlying paradigm is familiar, there are nonetheless a few important features of the ConsoleProgram class that are worth highlighting:

  Even though console-based interaction is comfortable for most teachers today, students who have grown up with modern graphical applications tend to find this style of interaction primitive and uninspiring. To avoid having them lose interest in computing altogether, it is important to introduce graphics and interactivity early in an introductory course. At the same time, the ConsoleProgram class has its place. Many instructors find that it is easier to illustrate how simple programming constructs work in a console-based environment because there aren’t as many complicating details to distract the student from the essential character of the construct in question. Similarly, console-based programs often provide a good framework for teaching problem-solving because students must focus on finding solution strategies instead of implementing the many graphical bells and whistles that can get in the way of fundamental ideas.

The DialogProgram class

The DialogProgram class is similar to ConsoleProgram except for one important detail. Instead of forwarding its input and output methods to a console, a DialogProgram implements those operations by popping up dialog boxes that deliver or request the same information. The print and println methods pop up a message dialog that contains the output line; the input methods like readInt and readLine pop up an input dialog that requests the information from the user. This difference is illustrated by the Add2Dialog program in Figure 1-6. Except for the fact that this version extends DialogProgram instead of ConsoleProgram, the code is identical to the Add2Console program from Figure 1-5. Running the Add2Dialog program produces a series of dialog boxes as shown in Figure 1-7.

Figure 1-6. Program to add two numbers entered via popup dialogs
/*
 * File: Add2Dialog.java
 * --------------------- 
 * This program adds two numbers and prints their sum.  Because
 * this version is a DialogProgram, the input and output appear
 * as popup dialogs.
 */
 
import acm.program.*;
 
public class Add2Dialog extends DialogProgram {
 
   public void run() {
      println("This program adds two numbers.");
      int n1 = readInt("Enter n1: ");
      int n2 = readInt("Enter n2: ");
      int total = n1 + n2;
      println("The total is " + total + ".");
   }
 
} 

  The DialogProgram class turns out to be valuable more for pedagogical than practical reasons. The advantage of having both the ConsoleProgram and the DialogProgram classes is that it emphasizes the nature of inheritance. The Add2Console program and the add2Dialog program have exactly the same run method. The difference in behavior comes from the fact that the two programs inherit operations from different Program subclasses.

Figure 1-7. Dialogs produced by the Add2Dialog program
     

  The similarity between the ConsoleProgram and DialogProgram classes underscores an important principle of object-oriented design. The input and output operations for these classes are specified by the IOModel interface in the acm.io package. This IOModel interface defines a set of methods that includes—along with several others—the methods print, println, readInt, readDouble, readLine, and showErrorMessage described in Figure 1-4. Because the code for the Program class declares that it implements IOModel, each of its subclasses will share that set of methods. Those methods, or course, are implemented in different ways, but they invariably have the same name and parameter structure.

The GraphicsProgram class

The GraphicsProgram class is by far the most interesting of the classes in the program hierarchy. As the HelloGraphics program made clear, a GraphicsProgram can present information on the screen in a way that holds at least a little more excitement than is possible with a ConsoleProgram. That example, however, merely scratched the surface of what is possible using the GraphicsProgram class. Because that class is far too powerful to cover in a single subsection, learning how to use the facilities provided by GraphicsProgram and the acm.graphics package on which it is based will take up the next two chapters in this tutorial. To unlock the power of graphics, read on.



JTF Tutorial—July 31, 2006