CLIK HERECLICK HERECLICK HERE  
CLICK HERECLICK HERE CLICK HERECLICK HERE

Java Applet Basics

  • Java Applet Basics
    • How Applets and Applications Are Different
    • Creating Applets
      • Major Applet Activities
        • Initialization
        • Starting
        • Stopping
        • Destroying
        • Painting
      • A Simple Applet
    • Including an Applet on a Web Page
      • The <APPLET> Tag
      • Testing the Result
      • Making Java Applets Available to the Web
    • More About the <APPLET> Tag
      • ALIGN
      • HSPACE and VSPACE
      • CODE and CODEBASE
    • Passing Parameters to Applets
    • Summary
    • Q&A


Java Applet Basics

by Laura Lemay
Much of Java's current popularity has come about because of Java-capable World Wide Web browsers and their support for applets: small programs that run inside a Web page and can be used to create dynamic, interactive Web designs. Applets, as I noted at the beginning of this book, are written in the Java language, and can be viewed in any browser that supports Java, including Sun's HotJava and Netscape's Navigator 2.0. Learning how to create applets is most likely the reason you bought this book, so let's waste no more time.
Last week, you focused on learning about the Java language itself, and most of the little programs you created were Java applications. This week, now that you have the basics down, you move on to creating and using applets, which includes a discussion of many of the classes in the standard Java class library.
Today, you'll start with the basics:
  • A small review of differences between Java applets and applications
  • Getting started with applets: the basics of how an applet works and how to create your own simple applets
  • Including an applet on a Web page by using the <APPLET> tag, including the various features of that tag
  • Passing parameters to applets

How Applets and Applications Are Different

Although you explored the differences between Java applications and Java applets in the early part of this book, let's review them.
In short, Java applications are stand-alone Java programs that can be run by using just the Java interpreter, for example, from a command line. Most everything you've used up to this point in the book has been a Java application, albeit a simple one.
Java applets, however, are run from inside a World Wide Web browser. A reference to an applet is embedded in a Web page using a special HTML tag. When a reader, using a Java-enabled browser, loads a Web page with an applet in it, the browser downloads that applet from a Web server and executes it on the local system (the one the browser is running on).
Because Java applets run inside a Java browser, they have the advantage of the structure the browser provides: an existing window, an event-handling and graphics context, and the surrounding user interface. Java applications can also create this structure, but they don't require it (you'll learn how to create Java applications that use applet-like graphics and UI features on Day 14).
The convenience that applets have over applications in terms of structure and UI capabilities, however, is hampered by restrictions on what applets can do. Given the fact that Java applets can be downloaded from anywhere and run on a client's system, restrictions are necessary to prevent an applet from causing system damage or security breaches. Without these restrictions in place, Java applets could be written to contain viruses or trojan horses (programs that seem friendly but do some sort of damage to the system), or be used to compromise the security of the system that runs them. The restrictions on what an applet can do include the following:
  • Applets can't read or write to the reader's file system, except in specific directories (which are defined by the user through an access control list that, by default, is empty). Some browsers may not even allow an applet to read or write to the file system at all, or at the same time as using the network.
  • Applets can't usually communicate with a server other than the one that had originally stored the applet. (This may be configurable by the browser; however, you should not depend on having this behavior available.)
  • Applets can't run any programs on the reader's system. For Unix systems, this includes forking a process.
  • Applets can't load programs native to the local platform, including shared libraries such as DLLs.
In addition, Java itself includes various forms of security and consistency checking in the Java compiler and interpreter to prevent unorthodox use of the language (you'll learn more about this on Day 21). This combination of restrictions and security features make it more difficult for a rogue Java applet to do damage to the client's system.
Note: These restrictions prevent all of the traditional ways of causing damage to a client's system, but it's impossible to be absolutely sure that a clever programmer cannot somehow work around these restrictions, violate privacy, use CPU resources, and be annoying. Sun has asked the Net at large to try to break Java's security and to create an applet that can work around the restrictions imposed on it. You'll learn about more issues in Java security on Day 21.

Creating Applets

For the most part, all the Java programs you've created up to this point have been Java applications—simple programs with a single main() method that created objects, set instance variables, and ran methods. Today and in the days following, you'll be creating applets exclusively, so you will need a good grasp of how an applet works, the sorts of features an applet has, and where to start when you first create your own applets. Without further ado, let's get on with it.
To create an applet, you create a subclass of the class Applet, in the java.applet package. The Applet class provides behavior to enable your applet not only to work within the browser itself, but also to take advantage of the capabilities of AWT to include UI elements, to handle mouse and keyword events, and to draw to the screen. Although your applet can have as many "helper" classes as it needs, it's the main applet class that triggers the execution of the applet. That initial applet class always has a signature like this:
public class myClass extends java.applet.Applet {

    ...

}
Note the public keyword. Java requires that your applet subclass be declared public. Again, this is true only of your main applet class; any helper classes you create can be public or private as you wish. Public, private, and other forms of access control are described on Day 15.
When Java encounters your applet in a Web page, it loads your initial applet class over the network, as well as any other helper classes that first class uses. Unlike with applications, where Java calls the main() method directly on your initial class, when your applet is loaded, Java creates an instance of that class, and a series of Applet methods are called on that instance. Different applets that use the same class use different instances, so each one can behave differently from the other applets running in the same browser.

Major Applet Activities

To create a basic Java application, your class has to have one method, main(), with a specific signature. Then, when your application starts up, main() is executed, and from main() you can set up the behavior that your program needs. Applets are similar but more complicated. Applets have many different activities that correspond to various major events in the life cycle of the applet—for example, initialization, painting, or mouse events. Each activity has a corresponding method, so when an event occurs, the browser or other Java-capable tool calls those specific methods.
The default implementations of these activity methods do nothing; to provide behavior for an event you must override the appropriate method in your applet's subclass. You don't have to override all of them, of course; different applet behavior requires different methods to be overridden.
You'll learn about the various important methods to override as the week progresses, but, for a general overview, here are five of the more important methods in an applet's execution: initialization, starting, stopping, destroying, and painting.
Initialization
Initialization occurs when the applet is first loaded (or reloaded). Initialization might include creating the objects it needs, setting up an initial state, loading images or fonts, or setting parameters. To provide behavior for the initialization of your applet, override the init() method:
public void init() {

    ...

}
Starting
After an applet is initialized, it is started. Starting can also occur if the applet was previously stopped. For example, an applet is stopped if the reader follows a link to a different page, and it is started again when the reader returns to this page. Note that starting can occur several times during an applet's life cycle, whereas initialization happens only once. To provide startup behavior for your applet, override the start() method:
public void start() {

    ...

}
Functionality that you put in the start() method might include starting up a thread to control the applet, sending the appropriate messages to helper objects, or in some way telling the applet to begin running. You'll learn more about starting applets on Day 10.
Stopping
Stopping and starting go hand in hand. Stopping occurs when the reader leaves the page that contains a currently running applet, or you can stop the applet yourself by calling stop(). By default, when the reader leaves a page any threads the applet had started will continue running. You'll learn more about threads in Day 10. By overriding stop(), you can suspend execution of these threads and then restart them if the applet is viewed again:
public void stop() {

    ...

}
Destroying
Destroying sounds more violent than it is. Destroying enables the applet to clean up after itself just before it is freed or the browser exits—for example, to kill any running threads or to release any other running objects. Generally, you won't want to override destroy() unless you have specific resources that need to be released—for example, threads that the applet has created. To provide clean up behavior for your applet, override the destroy() method:
public void destroy() {

    ...

}

Technical Note: How is destroy() different from finalize(), which was described on Day 7? First, destroy() applies only to applets. finalize() is a more general-purpose way for a single object of any type to clean up after itself.
Painting
Painting is how an applet actually draws something on the screen, be it text, a line, a colored background, or an image. Painting can occur many hundreds of times during an applet's life cycle—for example, once after the applet is initialized, if the browser is placed behind another window on the screen and then brought forward again, if the browser window is moved to a different position on the screen, or perhaps repeatedly in the case of animations. You override the paint() method for your applet to have an actual appearance on the screen. The paint() method looks like this:
public void paint(Graphics g) {

    ...

}
Note that unlike the other major methods in this section, paint() takes an argument, an instance of the class Graphics. This object is created and passed to paint by the browser, so you don't have to worry about it. However, you will have to make sure that the Graphics class (part of the java.awt package) gets imported into your applet code, usually through an import statement at the top of your Java file:
import java.awt.Graphics;

A Simple Applet

On Day 2, you created a simple applet called HelloAgainApplet (this was the one with the big red Hello Again). There, you created and used that applet as an example of creating a subclass. Let's go over the code for that applet again, this time looking at it slightly differently in light of the things you just learned about applets. Listing 8.1 shows the code for that applet.
    Listing 8.1. The Hello Again applet.
1:  import java.awt.Graphics;

 2:  import java.awt.Font;

 3:  import java.awt.Color;

 4:

 5:  public class HelloAgainApplet extends java.applet.Applet {

 6:

 7:     Font f = new Font("TimesRoman", Font.BOLD, 36);

 8:

 9:     public void paint(Graphics g) {

10:        g.setFont(f);

11:        g.setColor(Color.red);

12:        g.drawString("Hello again!", 5, 50);

13:     }

14: }
This applet overrides paint(), one of the major methods described in the previous section. Because the applet doesn't actually do much (all it does is print a couple of words to the screen), and there's not really anything to initialize, you don't need a start() or a stop() or an init() method.
The paint method is where the real work of this applet (what little work goes on) really occurs. The Graphics object passed into the paint() method holds the graphics state—that is, the current features of the drawing surface. Lines 10 and 11 set up the font and color for this graphics state (here, the font object held in the f instance variable, and an object representing the color red that's stored in the Color class's variable red).
Line 12 then draws the string "Hello Again!" by using the current font and color at the position 5, 50. Note that the 0 point for x, y is at the top left of the applet's drawing surface, with positive y moving downward, so 50 is actually at the bottom of the applet. Figure 8.1 shows how the applet's bounding box and the string are drawn on the page.

Figure 8.1. Drawing the applet.

Including an Applet on a Web Page

After you create a class or classes that contain your applet and compile them into class files as you would any other Java program, you have to create a Web page that will hold that applet by using the HTML language. There is a special HTML tag for including applets in Web pages; Java-capable browsers use the information contained in that tag to locate the compiled class files and execute the applet itself. In this section, you'll learn about how to put Java applets in a Web page and how to serve those files to the Web at large.
Note: The following section assumes you have at least a passing understanding of writing HTML pages. If you need help in this area, you may find the book Teach Yourself Web Publishing with HTML in 14 Days useful. It is also from Sams.Net (and also written by one of the authors of this book).

The <APPLET> Tag

To include an applet on a Web page, use the <APPLET> tag. <APPLET> is a special extension to HTML for including applets in Web pages. Listing 8.2 shows a very simple example of a Web page with an applet included in it.
    Listing 8.2. A simple HTML page.
1:  <HTML>

 2:  <HEAD>

 3:  <TITLE>This page has an applet on it</TITLE>

 4:  </HEAD>

 5:  <BODY>

 6:  <P>My second Java applet says:

 7:  <BR>

 8:  <APPLET CODE="HelloAgainApplet.class" WIDTH=200 HEIGHT=50>

 9:  There would be an applet here if your browser

10:  supported Java.

11:  </APPLET>

12:  </BODY>

13:  </HTML>
There are three things to note about the <APPLET> tag in this page:
  • The CODE attribute indicates the name of the class file that contains this applet, including the .class extension. In this case, the class file must be in the same directory as this HTML file. To indicate applets are in a specific directory, use CODEBASE, described later today.
  • WIDTH and HEIGHT are required and are used to indicate the bounding box of the applet—that is, how big a box to draw for the applet on the Web page. Be sure you set WIDTH and HEIGHT to be an appropriate size for the applet; depending on the browser, if your applet draws outside the boundaries of the space you've given it, you may not be able to see or get to those parts of the applet outside the bounding box.
  • The text between the <APPLET> and </APPLET> tags is displayed by browsers that do not understand the <APPLET> tag (which includes most browsers that are not Java-capable). Because your page may be viewed in many different kinds of browsers, it is a very good idea to include alternate text here so that readers of your page who don't have Java will see something other than a blank line. Here, you include a simple statement that says There would be an applet here if your browser supported Java.
Note that the <APPLET> tag, like the <IMG> tag, is not itself a paragraph, so it should be enclosed inside a more general text tag, such as <P> or one of the heading tags (<H1>, <H2>, and so on).

Testing the Result

Now with a class file and an HTML file that refers to your applet, you should be able to load that HTML file into your Java-capable browser (using either the Open File... menu item or a file URL, or by indicating the filename on a command line). The browser loads and parses your HTML file, and then loads and executes your applet class.
Figure 8.2 shows the Hello Again applet, in case you've forgotten what it looks like.

Figure 8.2. The Hello Again applet.

Making Java Applets Available to the Web

After you have an applet and an HTML file, and you've verified that everything is working correctly on your local system, the last step is making that applet available to the World Wide Web at large so that anyone with a Java-capable browser can view that applet.
Java applets are served by a Web server the same way that HTML files, images, and other media are. You don't need special server software to make Java applets available to the Web; you don't even need to configure your server to handle Java files. If you have a Web server up and running, or space on a Web server available to you, all you have to do is move your HTML and compiled class files to that server, as you would any other file.
If you don't have a Web server, you have to rent space on one or set one up yourself. (Web server setup and administration, as well as other facets of Web publishing in general, are outside the scope of this book.)

More About the <APPLET> Tag

In its simplest form, by using CODE, WIDTH, and HEIGHT, the <APPLET> tag merely creates a space of the appropriate size and then loads and runs the applet in that space. The <APPLET> tag, however, does include several attributes that can help you better integrate your applet into the overall design of your Web page.
Note: The attributes available for the <APPLET> tag are almost identical to those for the HTML <IMG> tag.

ALIGN

The ALIGN attribute defines how the applet will be aligned on the page. This attribute can have one of nine values: LEFT, RIGHT, TOP, TEXTTOP, MIDDLE, ABSMIDDLE, BASELINE, BOTTOM, and ABSBOTTOM.
In the case of ALIGN=LEFT and ALIGN=RIGHT, the applet is placed at the left or right margins of the page, respectively, and all text following that applet flows in the space to the right or left of that applet. The text will continue to flow in that space until the end of the applet, or you can use a line break tag (<BR>) with the CLEAR attribute to start the left line of text below that applet. The CLEAR attribute can have one of three values: CLEAR=LEFT starts the text at the next clear left margin, CLEAR=RIGHT does the same for the right margin, and CLEAR=ALL starts the text at the next line where both margins are clear.
For example, here's a snippet of HTML code that aligns an applet against the left margin, has some text flowing alongside it, and then breaks at the end of the paragraph so that the next bit of text starts below the applet:
<P><APPLET CODE="HelloAgainApplet" WIDTH=300 HEIGHT=200

ALIGN=LEFT>Hello Again!</APPLET>

To the left of this paragraph is an applet. It's a

simple, unassuming applet, in which a small string is

printed in red type, set in 36 point Times bold.

<BR CLEAR=ALL>

<P>In the next part of the page, we demonstrate how

under certain conditions, styrofoam peanuts can be

used as a healthy snack.
Figure 8.3 shows how this applet and the text surrounding it might appear in a Java-capable browser.
Figure 8.3. An applet aligned left.
For smaller applets, you may want to include your applet within a single line of text. To do this, there are seven values for ALIGN that determine how the applet is vertically aligned with the text:
  • ALIGN=TEXTTTOP aligns the top of the applet with the top of the tallest text in the line.
  • ALIGN=TOP aligns the applet with the topmost item in the line (which may be another applet, or an image, or the top of the text).
  • ALIGN=ABSMIDDLE aligns the middle of the applet with the middle of the largest item in the line.
  • ALIGN=MIDDLE aligns the middle of the applet with the middle of the baseline of the text.
  • ALIGN=BASELINE aligns the bottom of the applet with the baseline of the text. ALIGN=BASELINE is the same as ALIGN=BOTTOM, but ALIGN=BASELINE is a more descriptive name.
  • ALIGN=ABSBOTTOM aligns the bottom of the applet with the lowest item in the line (which may be the baseline of the text or another applet or image).
Figure 8.4 shows the various alignment options, where the line is an image and the arrow is a small applet.
Figure 8.4. Applet alignment options.

HSPACE and VSPACE

The HSPACE and VSPACE attributes are used to set the amount of space, in pixels, between an applet and its surrounding text. HSPACE controls the horizontal space (the space to the left and right of the applet). VSPACE controls the vertical space (the space above and below). For example, here's that sample snippet of HTML with vertical space of 50 and horizontal space of 10:
<P><APPLET CODE="HelloAgainApplet" WIDTH=300 HEIGHT=200

ALIGN=LEFT VSPACE=50 HSPACE=10>Hello Again!</APPLET>

To the left of this paragraph is an applet. It's a

simple, unassuming applet, in which a small string is

printed in red type, set in 36 point Times bold.

<BR CLEAR=ALL>

<P>In the next part of the page, we demonstrate how

under certain conditions, styrofoam peanuts can be

used as a healthy snack.
The result in a typical Java browser might look like that in Figure 8.5.
Figure 8.5. Vertical and horizontal space.

CODE and CODEBASE

CODE is used to indicate the name of the class file that holds the current applet. If CODE is used alone in the <APPLET> tag, the class file is searched for in the same directory as the HTML file that references it.
If you want to store your class files in a different directory than that of your HTML files, you have to tell the Java-capable browser where to find those class files. To do this, you use CODEBASE. CODE contains only the name of the class file; CODEBASE contains an alternate pathname where classes are contained. For example, if you store your class files in a directory called /classes, which is in the same directory as your HTML files, CODEBASE is the following:
<APPLET CODE="myclass.class" CODEBASE="classes"

    WIDTH=100 HEIGHT=100></APPLET>

Passing Parameters to Applets

With Java applications, you can pass parameters to your main() routine by using arguments on the command line. You can then parse those arguments inside the body of your class, and the application acts accordingly based on the arguments it is given.
Applets, however, don't have a command line. How do you pass in different arguments to an applet? Applets can get different input from the HTML file that contains the <APPLET> tag through the use of applet parameters. To set up and handle parameters in an applet, you need two things:
  • A special parameter tag in the HTML file
  • Code in your applet to parse those parameters
Applet parameters come in two parts: a name, which is simply a name you pick, and a value, which determines the value of that particular parameter. So, for example, you can indicate the color of text in an applet by using a parameter with the name color and the value red. You can determine an animation's speed using a parameter with the name speed and the value 5.
In the HTML fie that contains the embedded applet, you indicate each parameter using the <PARAM> tag, which has two attributes for the name and the value, called (surprisingly enough), NAME and VALUE. The <PARAM> tag goes inside the opening and closing <APPLET> tags:
<APPLET CODE="MyApplet.class" WIDTH=100 HEIGHT=100>

<PARAM NAME=font VALUE="TimesRoman">

<PARAM NAME=size VALUE="36">

A Java applet appears here.</APPLET>
This particular example defines two parameters to the MyApplet applet: one whose name is font and whose value is TimesRoman, and one whose name is size and whose value is 36.
Parameters are passed to your applet when it is loaded. In the init() method for your applet, you can then get hold of those parameters by using the getParameter() method. getParameter() takes one argument—a string representing the name of the parameter you're looking for—and returns a string containing the corresponding value of that parameter. (Like arguments in Java applications, all the parameter values are strings.) To get the value of the font parameter from the HTML file, you might have a line such as this in your init() method:
String theFontName = getParameter("font");

Note: The names of the parameters as specified in <PARAM> and the names of the parameters in getParameter() must match identically, including having the same case. In other words, <PARAM NAME="name"> is different from <PARAM NAME="Name">. If your parameters are not being properly passed to your applet, make sure the parameter cases match.
Note that if a parameter you expect has not been specified in the HTML file, getParameter() returns null. Most often, you will want to test for a null parameter and supply a reasonable default:
if (theFontName == null)

    theFontName = "Courier"
Keep in mind that getParameter() returns strings—if you want a parameter to be some other object or type, you have to convert it yourself. To parse the size parameter from that same HTML file and assign it to an integer variable called theSize, you might use the following lines:
int theSize;

String s = getParameter("size");

if (s == null)

    theSize = 12;

else theSize = Integer.parseInt(s);
Get it? Not yet? Let's create an example of an applet that uses this technique. You'll modify the HelloAgainApplet so that it says hello to a specific name, for example "Hello Bill" or "Hello Alice". The name is passed into the applet through an HTML parameter.
Let's start by copying the original HelloAgainApplet class:
import java.awt.Graphics;

import java.awt.Font;

import java.awt.Color;

public class MoreHelloApplet extends java.applet.Applet {

    Font f = new Font("TimesRoman", Font.BOLD, 36);

    public void paint(Graphics g) {

        g.setFont(f);

        g.setColor(Color.red);

        g.drawString("Hello Again!", 5, 50);

    }

}
The first thing you need to add to this class is a place for the name. Because you'll need that name throughout the applet, let's add an instance variable for the name, just after the variable for the font:
String name;
To set a value for the name, you have to get the parameter. The best place to handle parameters to an applet is inside an init() method. The init() method is defined similarly to paint() (public, with no arguments, and a return type of void). Make sure when you test for a parameter that you test for a value of null. The default, in this case, if a name isn't indicated, is to say hello to "Laura":
public void init() {

name = getParameter("name");

    if (name == null)

        name = "Laura";

    }
One last thing to do now that you have the name from the HTML parameters is to modify the name so that it's a complete string—that is, to tack "Hello " onto the beginning, and an exclamation point onto the end. You could do this in the paint method just before printing the string to the screen. Here it's done only once, however, whereas in paint() it's done every time the screen is repainted—in other words, it's slightly more efficient to do it inside init() instead:
name = "Hello " + name + "!";
And now, all that's left is to modify the paint() method. The original drawString() method looked like this:
g.drawString("Hello Again!", 5, 50);
To draw the new string you have stored in the name instance variable, all you need to do is substitute that variable for the literal string:
g.drawString(name, 5, 50);
Listing 8.3 shows the final result of the MoreHelloApplet class. Compile it so that you have a class file ready.
    Listing 8.3. The MoreHelloApplet class.
1:  import java.awt.Graphics;

 2:  import java.awt.Font;

 3:  import java.awt.Color;

 4:

 5:  public class MoreHelloApplet extends java.applet.Applet {

 6:

 7:     Font f = new Font("TimesRoman", Font.BOLD, 36);

 8:     String name;

 9:

10:     public void init() {

11:         name = getParameter("name");

12:         if (name == null)

13:             name = "Laura";

14:

15:         name = "Hello " + name + "!";

16:     }

17:

18:     public void paint(Graphics g) {

19:         g.setFont(f);

20:         g.setColor(Color.red);

21:         g.drawString(name, 5, 50);

22:     }

23: }
Now, let's create the HTML file that contains this applet. Listing 8.4 shows a new Web page for the MoreHelloApplet applet.
    Listing 8.4. The HTML file for the MoreHelloApplet applet.
1:  <HTML>

 2:  <HEAD>

 3:  <TITLE>Hello!</TITLE>

 4:  </HEAD>

 5:  <BODY>

 6:  <P>

 7:  <APPLET CODE="MoreHelloApplet.class" WIDTH=300 HEIGHT=50>

 8:  <PARAM NAME=name VALUE="Bonzo">

 9:  Hello to whoever you are!

10: </APPLET>

11: </BODY>

12: </HTML>
Note the <APPLET> tag, which points to the class file for the applet with the appropriate width and height (300 and 50). Just below it (line 8) is the <PARAM> tag, which you use to pass in the name. Here, the NAME parameter is simply name, and the VALUE is the string "Bonzo".
Loading up this HTML file produces the result shown in Figure 8.6.

Figure 8.6. The result of MoreHelloApplet, first try.
Let's try a second example. Remember that in the code for MoreHelloApplet, if no name is specified, the default is the name "Laura". Listing 8.5 creates an HTML file with no parameter tag for name.
    Listing 8.5. Another HTML File for the MoreHelloApplet applet.
1: <HTML>

 2: <HEAD>

 3: <TITLE>Hello!</TITLE>

 4: </HEAD>

 5: <BODY>

 6: <P>

 7: <APPLET CODE="MoreHelloApplet.class" WIDTH=300 HEIGHT=50>

 8: Hello to whoever you are!

 9: </APPLET>

10: </BODY>

11: </HTML>
Here, because no name was supplied, the applet uses the default, and the result is what you might expect (see Figure 8.7).
Figure 8.7. The result of MoreHelloApplet, second try.

Summary

Applets are probably the most common use of the Java language today. Applets are more complicated than many Java applications because they are executed and drawn inline within Web pages, but they can access the graphics, user interface, and event structure provided by the Web browser itself. Today, you learned the basics of creating applets, including the following things:
  • All applets you develop using Java inherit from the Applet class, part of the java.applet package. The Applet class provides basic behavior for how the applet will be integrated with and react to the browser and various forms of input from that browser and the person running it. By subclassing Applet, you have access to all that behavior.
  • Applets have five main methods, which are used for the basic activities an applet performs during its life cycle: init(), start(), stop(), destroy(), and paint(). Although you don't need to override all these methods, these are the most common methods you'll see repeated in many of the applets you'll create in this book and in other sample programs.
  • To run a compiled applet class file, you include it in an HTML Web page by using the <APPLET> tag. When a Java-capable browser comes across <APPLET>, it loads and runs the applet described in that tag. Note that to publish Java applets on the World Wide Web alongside HTML files you do not need special server software; any plain old Web server will do just fine.
  • Unlike applications, applets do not have a common line on which to pass arguments, so those arguments must be passed into the applet through the HTML file that contains it. You indicate parameters in an HTML file by using the <PARAM> tag inside the opening and closing <APPLET> tags. <PARAM> has two attributes: NAME for the name of the parameter, and VALUE for its value. Inside the body of your applet (usually in init()), you can then gain access to those parameters using the getParameter() method.

Q&A

Q: In the first part of today's lesson, you say that applets are downloaded from random Web servers and run on the client's system. What's to stop an applet developer from creating an applet that deletes all the files on that system, or in some other way compromises the security of the system? A: Recall that Java applets have several restrictions that make it difficult for all of the more obvious malicious behavior to take place. For example, because Java applets cannot read or write files on the client system, they cannot delete files or read system files that might contain private information. Because they cannot run programs on the client's system without your express permission, they cannot, for example, run system programs pretending to be you. Nor can they run so many programs that your system crashes.
In addition, Java's very architecture makes it difficult to circumvent these restrictions. The language itself, the Java compiler, and the Java interpreter all have checks to make sure that no one has tried to sneak in bogus code or play games with the system itself. You'll learn more about these checks at the end of this book.

Of course, no system can claim to be 100% secure, and the fact that Java applets are run on your system should make you suspicious—see Day 21 for more on security.
Q: Wait a minute. If I can't read or write files or run programs on the system the applet is running on, doesn't that mean I basically can't do anything other than simple animations and flashy graphics? How can I save state in an applet? How can I create, say, a word processor or a spreadsheet as a Java applet? A: For everyone who doesn't believe that Java is secure enough, there is someone who believes that Java's security restrictions are too severe for just these reasons. Yes, Java applets are limited because of the security restrictions. But given the possibility for abuse, I believe that it's better to err on the side of being more conservative as far as security is concerned. Consider it a challenge.
Keep in mind, also, that Java applications have none of the restrictions that Java applets do, but because they are also compiled to bytecode, they are portable across platforms. It may be that the thing you want to create would make a much better application than an applet.
Q: I have an older version of HotJava. I followed all the examples in this section, but HotJava cannot read my applets (it seems to ignore them). What's going on? A: You most likely have an alpha version of HotJava. Recall that significant changes were made to the Java API and how Java applets are written between alpha and the 1.0 release. The results of these changes are that browsers that support alpha applets cannot read beta applets, and vice versa. The HTML tags are even different, so an older browser just skips over newer applets, and vice versa.
By the time you read this, there may be a new version of HotJava with support for 1.0. If not, you can use Netscape 2.0 or the JDK's applet viewer to view applets written to the beta specification.
Q: I noticed in my documentation that the <APPLET> tag also has a NAME attribute. You didn't discuss it here. A: NAME is used when you have multiple applets on a page that need to communicate with each other. You'll learn about this on Day 12. Q: I have an applet that takes parameters and an HTML file that passes it those parameters. But when my applet runs, all I get are null values. What's going on here? A: Do the names of your parameters (in the NAME attribute) match exactly with the names you're testing for in getParameter()? They must be exact, including case, for the match to be made. Make sure also that your <PARAM> tags are inside the opening and closing <APPLET> tags, and that you haven't misspelled anything.

More About Methods

  • More About Methods
    • Creating Methods with the Same Name, Different Arguments
    • Constructor Methods
      • Basic Constructors
      • Calling Another Constructor
      • Overloading Constructors
    • Overriding Methods
      • Creating Methods that Override Existing Methods
      • Calling the Original Method
      • Overriding Constructors
    • Finalizer Methods
    • Summary
    • Q&A


More About Methods

by Laura Lemay Methods are arguably the most important part of any object-oriented language. Whereas classes and objects provide the framework, and class and instance variables provide a way of holding that class or object's attributes and state, it is the methods that actually provide an object's behavior and define how that object interacts with other objects in the system.
Yesterday, you learned a little about defining methods. With what you learned yesterday, you could create lots of Java programs, but you'd be missing some of the features of methods that make them really powerful, that make your objects and classes more efficient and easier to understand. Today, you'll learn about these additional features, including the following:
  • Overloading methods—that is, creating methods with multiple signatures and definitions but with the same name
  • Creating constructor methods—methods that enable you to initialize objects to set up their initial state when created
  • Overriding methods—creating a different definition for a method that has been defined in a superclass
  • Finalizer methods—a way for an object to clean up after itself before it is removed from the system

Creating Methods with the Same Name, Different Arguments

Yesterday, you learned how to create methods with a single name and a single signature. Methods in Java can also be overloaded—that is, you can create methods that have the same name, but different signatures and different definitions. Method overloading enables instances of your class to have a simpler interface to other objects (no need for entirely different methods that do essentially the same thing) and to behave differently based on the input to that method.
When you call a method in an object, Java matches up the method name and the number and type of arguments to choose which method definition to execute.
To create an overloaded method, all you need to do is create several different method definitions in your class, all with the same name, but with different parameter lists (either in number or type of arguments). Java allows method overloading as long as each parameter list is unique for the same method name.
Note that Java differentiates overloaded methods with the same name, based on the number and type of parameters to that method, not on its return type. That is, if you try to create two methods with the same name, same parameter list, but different return types, you'll get a compiler error. The variable names you choose for each parameter to the method are irrelevant—all that matters is the number and the type.
Here's an example of creating an overloaded method. Listing 7.1 shows a simple class definition for a class called MyRect, which defines a rectangular shape. The MyRect class has four instance variables to define the upper left and lower right corners of the rectangle: x1, y1, x2, and y2.

Note: Why did I call it MyRect? Java's awt package has a class called Rectangle that implements much of this same behavior. I called this class MyRect to prevent confusion between the two classes.
    Listing 7.1. The MyRect class.
class MyRect {

    int x1 = 0;

    int y1 = 0;

    int x2 = 0;

    int y2 = 0;

}
When a new instance of the myRect class is initially created, all its instance variables are initialized to 0. Let's define a buildRect() method that takes four integer arguments and "resizes" the rectangle to have the appropriate values for its corners, returning the resulting rectangle object (note that because the arguments have the same names as the instance variables, you have to make sure to use this to refer to them):
MyRect buildRect(int x1, int y1, int x2, int y2) {

    this.x1 = x1;

    this.y1 = y1;

    this.x2 = x2;

    this.y2 = y2;

    return this;

}
What if you want to define a rectangle's dimensions in a different way—for example, by using Point objects rather than individual coordinates? You can overload buildRect() so that its parameter list takes two Point objects (note that you'll need to import the Point class at the top of your source file so Java can find it):
MyRect buildRect(Point topLeft, Point bottomRight) {

    x1 = topLeft.x;

    y1 = topLeft.y;

    x2 = bottomRight.x;

    y2 = bottomRight.y;

    return this;

}
Perhaps you want to define the rectangle using a top corner and a width and height. Just create a different definition for buildRect():
MyRect buildRect(Point topLeft, int w, int h) {

    x1 = topLeft.x;

    y1 = topLeft.y;

    x2 = (x1 + w);

    y2 = (y1 + h);

    return this;

}
To finish up this example, let's create a method to print out the rectangle's coordinates, and a main() method to test it all (just to prove that this does indeed work). Listing 7.2 shows the completed class definition with all its methods.
    Listing 7.2. The complete MyRect class.
import java.awt.Point;

class MyRect {

    int x1 = 0;

    int y1 = 0;

    int x2 = 0;

    int y2 = 0;

    MyRect buildRect(int x1, int y1, int x2, int y2) {

        this.x1 = x1;

        this.y1 = y1;

        this.x2 = x2;

        this.y2 = y2;

        return this;

    }

    MyRect buildRect(Point topLeft, Point bottomRight) {

        x1 = topLeft.x;

        y1 = topLeft.y;

        x2 = bottomRight.x;

        y2 = bottomRight.y;

        return this;

    }

    MyRect buildRect(Point topLeft, int w, int h) {

        x1 = topLeft.x;

        y1 = topLeft.y;

        x2 = (x1 + w);

        y2 = (y1 + h);

        return this;

    }

    void printRect(){

        System.out.print("MyRect: <" + x1 + ", " + y1);

        System.out.println(", " + x2 + ", " + y2 + ">");

    }

    public static void main(String args[]) {

        MyRect rect = new MyRect();

        System.out.println("Calling buildRect with coordinates 25,25 50,50:");

        rect.buildRect(25, 25, 50, 50);

        rect.printRect();

        System.out.println("—————");

        System.out.println("Calling buildRect w/points (10,10), (20,20):");

        rect.buildRect(new Point(10,10), new Point(20,20));

        rect.printRect();

        System.out.println("—————");

        System.out.print("Calling buildRect w/1 point (10,10),");

        System.out.println(" width (50) and height (50)");

        rect.buildRect(new Point(10,10), 50, 50);

        rect.printRect();

        System.out.println("—————");

    }

}
Here's the output of this Java program:
Calling buildRect with coordinates 25,25 50,50:

MyRect: <25, 25, 50, 50>

—————

Calling buildRect w/points (10,10), (20,20):

MyRect: <10, 10, 20, 20>

—————

Calling buildRect w/1 point (10,10), width (50) and height (50)

MyRect: <10, 10, 60, 60>

—————
As you can see from this example, all the buildRect() methods work based on the arguments with which they are called. You can define as many versions of a method as you need to in your own classes to implement the behavior you need for that class.

Constructor Methods

In addition to regular methods, you can also define constructor methods in your class definition.
A constructor method is a special kind of method that determines how an object is initialized when it's created.
Unlike regular methods, you can't call a constructor method by calling it directly; instead, constructor methods are called by Java automatically. Here's how it works: when you use new to create a new instance of a class, Java does three things:
  • Allocates memory for the object
  • Initializes that object's instance variables, either to their initial values or to a default (0 for numbers, null for objects, false for booleans, '\0' for characters)
  • Calls the class's constructor method (which may be one of several methods)
If a class doesn't have any special constructor methods defined, you'll still end up with an object, but you might have to set its instance variables or call other methods that object needs to initialize itself. All the examples you've created up to this point have behaved like this.
By defining constructor methods in your own classes, you can set initial values of instance variables, call methods based on those variables or call methods on other objects, or calculate initial properties of your object. You can also overload constructors, as you would regular methods, to create an object that has specific properties based on the arguments you give to new.

Basic Constructors

Constructors look a lot like regular methods, with two basic differences:
  • Constructors always have the same name as the class.
  • Constructors don't have a return type.
For example, Listing 7.3 shows a simple class called Person, with a constructor that initializes its instance variables based on the arguments to new. The class also includes a method for the object to introduce itself, and a main() method to test each of these things.
    Listing 7.3. The Person class.
class Person {

    String name;

    int age;

    Person(String n, int a) {

        name = n;

        age = a;

    }

    void printPerson() {

        System.out.print("Hi, my name is " + name);

        System.out.println(". I am " + age + " years old.");

    }

    public static void main (String args[]) {

        Person p;

        p = new Person("Laura", 20);

        p.printPerson();

        System.out.println("————");

        p = new Person("Tommy", 3);

        p.printPerson();

        System.out.println("————");

    }

}
Here's the output for this example program:
Hi, my name is Laura. I am 20 years old.

————

Hi, my name is Tommy. I am 3 years old.

————

Calling Another Constructor

Some constructors you write may be a superset of another constructor defined in your class; that is, they might have the same behavior plus a little bit more. Rather than duplicating identical behavior in multiple constructor methods in your class, it makes sense to be able to just call that first constructor from inside the body of the second constructor. Java provides a special syntax for doing this. To call a constructor defined on the current class, use this form:
this(arg1, arg2, arg3...);
The arguments to this are, of course, the arguments to the constructor.

Overloading Constructors

Like regular methods, constructors can also take varying numbers and types of parameters, enabling you to create your object with exactly the properties you want it to have, or for it to be able to calculate properties from different kinds of input.
For example, the buildRect() methods you defined in the MyRect class earlier today would make excellent constructors, because what they're doing is initializing an object's instance variables to the appropriate values. So, instead of the original buildRect() method you had defined (which took four parameters for the coordinates of the corners), you can create a constructor instead. Listing 7.4 shows a new class, called MyRect2, that has all the same functionality of the original MyRect, except with overloaded constructor methods instead of the buildRect() method.
    Listing 7.4. The MyRect2 class (with constructors).
import java.awt.Point;

class MyRect2 {

    int x1 = 0;

    int y1 = 0;

    int x2 = 0;

    int y2 = 0;

    MyRect2(int x1, int y1, int x2, int y2) {

        this.x1 = x1;

        this.y1 = y1;

        this.x2 = x2;

        this.y2 = y2;

    }

    MyRect2(Point topLeft, Point bottomRight) {

        x1 = topLeft.x;

        y1 = topLeft.y;

        x2 = bottomRight.x;

        y2 = bottomRight.y;

    }

    MyRect2(Point topLeft, int w, int h) {

        x1 = topLeft.x;

        y1 = topLeft.y;

        x2 = (x1 + w);

        y2 = (y1 + h);

    }

    void printRect() {

        System.out.print("MyRect: <" + x1 + ", " + y1);

        System.out.println(", " + x2 + ", " + y2 + ">");

    }

    public static void main(String args[]) {

        MyRect2 rect;

        System.out.println("Calling MyRect2 with coordinates 25,25 50,50:");

        rect = new MyRect2(25, 25, 50,50);

        rect.printRect();

        System.out.println("—————");

        System.out.println("Calling MyRect2 w/points (10,10), (20,20):");

        rect= new MyRect2(new Point(10,10), new Point(20,20));

        rect.printRect();

        System.out.println("—————");

        System.out.print("Calling MyRect2 w/1 point (10,10),");

        System.out.println(" width (50) and height (50)");

        rect = new MyRect2(new Point(10,10), 50, 50);

        rect.printRect();

        System.out.println("—————");

    }

}
Here's the output for this example program (it's the same output from the previous example; only the code to produce it has changed):
Calling MyRect2 with coordinates 25,25 50,50:

MyRect: <25, 25, 50, 50>

—————

Calling MyRect2 w/points (10,10), (20,20):

MyRect: <10, 10, 20, 20>

—————

Calling MyRect2 w/1 point (10,10), width (50) and height (50)

MyRect: <10, 10, 60, 60>

—————

Overriding Methods

When you call a method on an object, Java looks for that method definition in the class of that object, and if it doesn't find one, it passes the method call up the class hierarchy until a method definition is found. Method inheritance enables you to define and use methods repeatedly in subclasses without having to duplicate the code itself.
However, there may be times when you want an object to respond to the same methods but have different behavior when that method is called. In this case, you can override that method. Overriding a method involves defining a method in a subclass that has the same signature as a method in a superclass. Then, when that method is called, the method in the subclass is found and executed instead of the one in the superclass.

Creating Methods that Override Existing Methods

To override a method, all you have to do is create a method in your subclass that has the same signature (name, return type, and parameter list) as a method defined by one of your class's superclasses. Because Java executes the first method definition it finds that matches the signature, this effectively "hides" the original method definition. Here's a simple example; Listing 7.5 shows a simple class with a method called printMe(), which prints out the name of the class and the values of its instance variables.
    Listing 7.5. The PrintClass class.
class PrintClass {

    int x = 0;

    int y = 1;

    void printMe() {

        System.out.println("X is " + x + ", Y is " + y);

        System.out.println("I am an instance of the class " +

        this.getClass().getName());

    }

}
Listing 7.6 shows a class called PrintSubClass that is a subclass of (extends) PrintClass. The only difference between PrintClass and PrintSubClass is that the latter has a z instance variable.
    Listing 7.6. The PrintSubClass class.
class PrintSubClass extends PrintClass {

    int z = 3;

    public static void main(String args[]) {

        PrintSubClass obj = new PrintSubClass();

        obj.printMe();

    }

}
Here's the output from PrintSubClass:
X is 0, Y is 1

I am an instance of the class PrintSubClass
In the main() method of PrintSubClass, you create a PrintSubClass object and call the printMe() method. Note that PrintSubClass doesn't define this method, so Java looks for it in each of PrintSubClass's superclasses—and finds it, in this case, in PrintClass. Unfortunately, because printMe() is still defined in PrintClass, it doesn't print the z instance variable.
Now, let's create a third class. PrintSubClass2 is nearly identical to PrintSubClass, but you override the printMe() method to include the z variable. Listing 7.7 shows this class.
    Listing 7.7. The PrintSubClass2 class.
class PrintSubClass2 extends PrintClass {

    int z = 3;

    void printMe() {

        System.out.println("x is " + x + ", y is " + y +

               ", z is " + z);

        System.out.println("I am an instance of the class " +

               this.getClass().getName());

    }

    public static void main(String args[]) {

        PrintSubClass2 obj = new PrintSubClass2();

        obj.printMe();

    }

}
Now, when you instantiate this class and call the printMe() method, the version of printMe() you defined for this class is called instead of the one in the superclass PrintClass (as you can see in this output):
x is 0, y is 1, z is 3

I am an instance of the class PrintSubClass2

Calling the Original Method

Usually, there are two reasons why you want to override a method that a superclass has already implemented:
  • To replace the definition of that original method completely
  • To augment the original method with additional behavior
You've already learned about the first one; by overriding a method and giving that method a new definition, you've hidden the original method definition. But sometimes you may just want to add behavior to the original definition rather than erase it altogether. This is particularly useful where you end up duplicating behavior in both the original method and the method that overrides it; by being able to call the original method in the body of the overridden method, you can add only what you need.
To call the original method from inside a method definition, use the super keyword to pass the method call up the hierarchy:
void myMethod (String a, String b) {

    // do stuff here

    super.myMethod(a, b);

    // maybe do more stuff here

}
The super keyword, somewhat like the this keyword, is a placeholder for this class's superclass. You can use it anywhere you can use this, but to refer to the superclass rather than to the current class.
For example, Listing 7.8 shows those printMe() methods used in the previous example.
    Listing 7.8. The printMe methods.
// from PrintClass

void printMe() {

        System.out.println("X is " + x + ", Y is " + y);

        System.out.println("I am an instance of the class" +

               this.getClass().getName());

    }

}

//from PrintSubClass2

    void printMe() {

        System.out.println("X is " + x + ", Y is " + y + ", Z is " + z);

        System.out.println("I am an instance of the class " +

               this.getClass().getName());

    }
Rather than duplicating most of the behavior of the superclass's method in the subclass, you can rearrange the superclass's method so that additional behavior can easily be added:
// from PrintClass

void printMe() {

    System.out.println("I am an instance of the class" +

                 this.getClass().getName());

    System.out.println("X is " + x);

    System.out.println("Y is " + y);

}
Then, in the subclass, when you override printMe, you can merely call the original method and then add the extra stuff:
// From PrintSubClass2

void printMe() {

    super.printMe();

    System.out.println("Z is " + z);

}
Here's the output of calling printMe() on an instance of the subclass:
I am an instance of the class PrintSubClass2

X is 0

Y is 1

Z is 3

Overriding Constructors

Constructors cannot technically be overridden. Because they always have the same name as the current class, you're always creating new constructors instead of inheriting the ones you've got. Much of the time, this is fine, because when your class's constructor is called, the constructor with the same signature for all your superclass is also called, so initialization of all the parts of a class you inherit can happen.
However, when you're defining constructors for your own class, you may want to change how your object is initialized, not only by initializing new variables your class adds, but also to change the contents of variables that are already there. You do this by explicitly calling your superclass's constructors, and then changing whatever you like.
To call a regular method in a superclass, you use super.methodname(arguments). Because with constructors you don't have a method name to call, however, you have to use a different form:
super(arg1, arg2, ...);
Similar to using this(...) in a constructor, super(...) calls the constructor method for the immediate superclass (which may, in turn, call the constructor of its superclass, and so on).
For example, Listing 7.9 shows a class called NamedPoint, which extends the class Point from Java's awt package. The Point class has only one constructor, which takes an x and a y argument and returns a Point object. NamedPoint has an additional instance variable (a string for the name) and defines a constructor to initialize x, y, and the name.
    Listing 7.9. The NamedPoint class.
1: import java.awt.Point;

2: class NamedPoint extends Point {

3:     String name;

4:

5:     NamedPoint(int x, int y, String name) {

6:        super(x,y);

7:         this.name = name;

8:     }

9: }
The constructor defined here for NamedPoint (lines 6 through 8) calls Point's constructor method to initialize Point's instance variables (x and y). Although you can just as easily initialize x and y yourself, you may not know what other things Point is doing to initialize itself, so it's always a good idea to pass constructors up the hierarchy to make sure everything is set up correctly.

Finalizer Methods

Finalizer methods are like the opposite of constructor methods; whereas a constructor method is used to initialize an object, finalizer methods are called just before the object is garbage-collected and its memory reclaimed.
The finalizer method is simply finalize(). The Object class defines a default finalizer method, which does nothing. To create a finalizer method for your own classes, override the finalize() method using this signature:
protected void finalize() {

    ...

}
Inside the body of that finalize() method, include any cleaning up you want to do for that object. You can also call super.finalize() to allow your class's superclasses to finalize your object, if necessary.
You can always call the finalize() method yourself at any time; it's just a plain method like any other. However, calling finalize() does not trigger an object to be garbage-collected. Only removing all references to an object will cause it to be marked for deleting.
Finalizer methods are best used for optimizing the removal of an object—for example, by removing references to other objects, by releasing external resources that have acquired, or for other behaviors that may make it easier for that object to be removed. In most cases, you will not need to use finalize() at all. See Day 21 for more about garbage collection and finalize().

Summary

Today, you learned all kinds of techniques for using, reusing, defining, and redefining methods. You learned how to overload a method name so that the same method can have different behaviors based on the arguments with which it's called. You learned about constructor methods, which are used to initialize a new object when it's created. You learned about method inheritance and how to override methods that have been defined in a class's superclasses. Finally, you learned about finalizer methods, that can be used to clean up after an object just before that object is garbage-collected and its memory reclaimed.
Congratulations on completing your first week of Teach Yourself Java in 21 Days! Starting next week, you'll apply everything you've learned this week to writing Java applets and to working with more advanced concepts in putting together Java programs and working with the standard Java class libraries.

Q&A

Q: I created two methods with the following signatures:
int total(int arg1, int arg2, int arg3) {...} float total(int arg1, int arg2, int arg3) {...}
The Java compiler complains when I try to compile the class with these method definitions. But their signatures are different—what have I done wrong? A: Method overloading in Java works only if the parameter lists are different—either in number or type of arguments. Return type is not relevant for method overloading. Think about it—if you had two methods with exactly the same parameter list, how would Java know which one to call? Q: Can I overload overridden methods (that is, can I create methods that have the same name as an inherited method, but a different parameter list)? A: Sure! As long as a parameter lists vary, it doesn't matter whether you've defined a new method name or one that you've inherited from a superclass.

Creating Classes and Applications in Java

  • Creating Classes and Applications in Java
    • Defining Classes
    • Creating Instance and Class Variables
      • Defining Instance Variables
      • Constants
      • Class Variables
  • Creating Methods
    • Defining Methods
    • The this Keyword
    • Variable Scope and Method Definitions
    • Passing Arguments to Methods
    • Class Methods
  • Creating Java Applications
  • Java Applications and Command-Line Arguments
    • Passing Arguments to Java Programs
    • Handling Arguments in Your Java Program
  • Summary
  • Q&A


Creating Classes and Applications in Java

By Laura Lemay In just about every lesson up to this point you've been creating Java applications—writing classes, creating instance variables and methods, and running those applications to perform simple tasks. Also up to this point, you've focused either on the very broad (general object-oriented theory) or the very minute (arithmetic and other expressions). Today, you pull it all together and learn how and why to create classes by using the following basics:
  • The parts of a class definition
  • Declaring and using instance variables
  • Defining and using methods
  • Creating Java applications, including the main() method and how to pass arguments to a Java program from a command line

Defining Classes

Defining classes is pretty easy; you've seen how to do it a bunch of times in previous lessons. To define a class, use the class keyword and the name of the class:
class MyClassName {

...

}
If this class is a subclass of another class, use extends to indicate the superclass of this class:
class myClassName extends mySuperClassName {

...

}
If this class implements a specific interface, use implements to refer to that interface:
class MyRunnableClassName implements Runnable {

...

}
Both extends and implements are optional. You'll learn about using and defining interfaces in Week 3.

Creating Instance and Class Variables

A class definition with nothing in it is pretty dull; usually, when you create a class, you have something you want to add to make that class different from its superclasses. Inside each class definition are declarations and definitions for variables or methods or both 7Äfor the class and for each instance. In this section, you'll learn all about instance and class variables; the next section talks about methods.

Defining Instance Variables

On Day 3, you learned how to declare and initialize local variables—that is, variables inside method definitions. Instance variables, fortunately, are declared and defined in almost exactly the same way as local variables; the main difference is their location in the class definition. Variables are considered instance variables if they are declared outside a method definition. Customarily, however, most instance variables are defined just after the first line of the class definition. For example, Listing 6.1 shows a simple class definition for the class Bicycle, which inherits from the class PersonPoweredVehicle. This class definition contains four instance variables:
  • bikeType: the kind of bicycle this bicycle is—for example, Mountain or Street
  • chainGear, the number of gears in the front
  • rearCogs, the number of minor gears on the rear axle
  • currentGearFront and currentGearRear: the gears the bike is currently in, both front and rear
  • Listing 6.1. The bicycle class.
1: class Bicycle extends PersonPoweredVehicle {

2:     String bikeType;

3:     int chainGear;

4:     int rearCogs;

5:     int currentGearFront;

6:     int currentGearRear;

7: }

Constants

Constants are useful for defining shared values for all the mothods of an object— for giving meaningful names to object-wide values that will never change. In Java, you can create constants only for instance or class variables, not for local variables. A constant variable or constant is a variable whose value never changes (which may seem strange given the meaning of the word "variable"). To declare a constant, use the final keyword before the variable declaration and include an initial value for that variable:
final float pi = 3.141592;

final boolean debug = false;

final int maxsize = 40000;

Technical Note: The only way to define constants in Java is by using the final keyword. Neither the C and C++ constructs for #define nor const are available in Java, though const is reserved to help catch its accidental use.
Constants can be useful for naming various states of an object and then testing for those states. For example, suppose you have a test label that can be aligned left, right, or center. You can define those values as constant integers:
final int LEFT = 0;

final int RIGHT = 1;

final int CENTER = 2;
The variable alignment is then also declared as an int:
int alignment;
Then, later on in the body of a method definition, you can either set the alignment:
this.alignment = CENTER;
or test for a given alignment:
switch (this.alignment) {

    case LEFT: // deal with left alignment

               ...

               break;

    case RIGHT: // deal with right alignment

                ...

                break;

    case CENTER: // deal with center alignment

                 ...

                 break;

}

Class Variables

As you learned in previous lessons, class variables are global to a class and to all that class's instances. You can think of class variables as being even more global than instance variables. Class variables are good for communicating between different objects with the same class, or for keeping track of global states among a set of objects. To declare a class variable, use the static keyword in the class declaration:
static int sum;

static final int maxObjects = 10;

Creating Methods

Methods, as you learned on Day 2, define an object's behavior—what happens when that object is created and the various operations that object can perform during its lifetime. In this section, you'll get a basic introduction to method definition and how methods work; tomorrow, you'll go into more detail about advanced things you can do with methods.

Defining Methods

Method definitions have four basic parts:
  • The name of the method
  • The type of object or primitive type the method returns
  • A list of parameters
  • The body of the method
The method's signature is a combination of the name of the method, the type of object or base type this method returns, and a list of parameters.
Note: To keep things simple today, I've left off two optional parts of the method definition: a modifier such as public or private, and the throws keyword, which indicates the exceptions a method can throw. You'll learn about these parts of a method definition in Week 3.
In other languages, the name of the method (or function, subroutine, or procedure) is enough to distinguish it from other methods in the program. In Java, you can have different methods that have the same name but a different return type or argument list. This is called method overloading, and you'll learn more about it tomorrow. Here's what a basic method definition looks like:
returntype methodname(type1 arg1, type2 arg2, type3 arg3..) {

    ...

}
The returntype is the primitive type or class of the of the value this method returns. It can be one of the primitive types, a class name, or void if the method does not return a value at all. Note that if this method returns an array object, the array brackets can go either after the return type or after the parameter list; because the former way is considerably easier to read, it is used in the examples today (and throughout this book):
int[] makeRange(int lower, int upper) {...}
The method's parameter list is a set of variable declarations, separated by commas, inside parentheses. These parameters become local variables in the body of the method, whose values are the objects or values of primitives passed in when the method is called. Inside the body of the method you can have statements, expressions, method calls to other objects, conditionals, loops, and so on—everything you've learned about in the previous lessons. If your method has a real return type (that is, it has not been declared to return void), somewhere inside the body of the method you need to return a value. Use the return keyword to do this. Listing 6.2 shows an example of a class that defines a makeRange() method. makeRange() takes two integers—a lower bound and an upper bound—and creates an array that contains all the integers between those two boundaries (inclusive).
    Listing 6.2. The RangeClass class.
 1: class RangeClass {

 2:     int[] makeRange(int lower, int upper) {

 3:         int arr[] = new int[ (upper - lower) + 1 ];

4: 

 5:         for (int i = 0; i < arr.length; i++) {

 6:             arr[i] = lower++;

 7:         }

 8:         return arr;

 9:     }

10:         

11:     public static void main(String arg[]) {

12:         int theArray[];

13:         RangeClass theRange = new RangeClass();

14: 

15:         theArray = theRange.makeRange(1, 10);

16:         System.out.print("The array: [ ");

17:         for (int i = 0; i < theArray.length; i++) {

18:             System.out.print(theArray[i] + " ");

19:         }

20:         System.out.println("]");

21:     }

22: 

23: }
Here's the output of this program:
The array: [ 1 2 3 4 5 6 7 8 9 10 ]
The main() method in this class tests the makeRange() method by creating a range where the lower and upper boundaries of the range are 1 and 10, respectively (see line 6), and then uses a for loop to print the values of the new array.

The this Keyword

In the body of a method definition, you may want to refer to the current object—the object the method was called on— to refer to that object's instance variables or to pass the current object as an argument to another method. To refer to the current object in these cases, you can use the this keyword. this refers to the current object, and you can use it anywhere that object might appear—in dot notation to refer to the object's instance variables, as an argument to a method, as the return value for the current method, and so on. Here's an example:
t = this.x          // the x instance variable for this object

this.myMethod(this) // call the mymethod method, defined in

                    // this class, and pass it the current

                    // object

return this;        // return the current object
In many cases, however, you may be able to omit the this keyword. You can refer to both instance variables and method calls defined in the current class simply by name; the this is implicit in those references. So, the first two examples could be written like this:
t = x          // the x instance variable for this object

myMethod(this) // call the myMethod method, defined in this

               // class

Note: Omitting the this keyword for instance variables depends on whether there are no variables of the same name declared in the local scope. See the next section for details.
Keep in mind that because this is a reference to the current instance of a class, therefore you should only use it inside the body of an instance method definition. Class methods, that is, methods declared with the static keyword, cannot use this.

Variable Scope and Method Definitions

When you refer to a variable within your method definitions, Java checks for a definition of that variable first in the current scope (which may be a block), then in the outer scopes up to the current method definition. If that variable is not a local variable, Java then checks for a definition of that variable as an instance or class variable in the current class, and then, finally, in each superclass in turn. Because of the way Java checks for the scope of a given variable, it is possible for you to create a variable in a lower scope such that a definition of that same variable "hides" the original value of that variable. This can introduce subtle and confusing bugs into your code. For example, note this small Java program:
class ScopeTest {

    int test = 10;

    void printTest () {

        int test = 20;

        System.out.println("test = " + test);

    }

}
In this class, you have two variables with the same name and definition: the first, an instance variable, has the name test and is initialized to the value 10. The second is a local variable with the same name, but with the value 20. Because the local variable hides the instance variable, the println() method will print that test is 20. You can get around this particular problem by using this.test to refer to the instance variable, and just test to refer to the local variable. A more insidious example of this occurs when you redefine a variable in a subclass that already occurs in a superclass. This can create very subtle bugs in your code—for example, you may call methods that are intended to change the value of an instance variable, but that change the wrong one. Another bug might occur when you cast an object from one class to another—the value of your instance variable may mysteriously change (because it was getting that value from the superclass instead of from your class). The best way to avoid this behavior is to make sure that, when you define variables in a subclass, you're aware of the variables in each of that class's superclasses and you don't duplicate what is already there.

Passing Arguments to Methods

When you call a method with object parameters, the variables you pass into the body of the method are passed by reference, which means that whatever you do to those objects inside the method affects the original objects as well. This includes arrays and all the objects that arrays contain; when you pass an array into a method and modify its contents, the original array is affected. (Note that primitive types are passed by value.) Here's an example to demonstrate how this works. First, you have a simple class definition, which includes a single method called OneToZero() (see Listing 6.3).
    Listing 6.3. The PassByReference class.
 1: class PassByReference {

 2:     int onetoZero(int arg[]) {

 3:         int count = 0;

 4: 

 5:         for (int i = 0; i < arg.length; i++) {

 6:             if (arg[i] == 1) {

 7:                 count++;

 8:                 arg[i] = 0;

 9:             }

10:         }

11:         return count;

12:     }

13: }
The onetoZero() method does two things:
  • It counts the number of ones in the array and returns that value.
  • If it finds a one, it substitutes a zero in its place in the array.
Listing 6.4 shows the main() method for the PassByReference class, which tests the onetoZero() method:
    Listing 6.4. The main() method in PassByReference.
 1: public static void main (String arg[]) {

 2:     int arr[] = { 1, 3, 4, 5, 1, 1, 7 };

 3:     PassByReference test = new PassByReference();

 4:     int numOnes;

 5:     

 6:     System.out.print("Values of the array: [ ");

 7:     for (int i = 0; i < arr.length; i++) {

 8:         System.out.print(arr[i] + " ");

 9:     }

10:     System.out.println("]");

11:     

12:     numOnes = test.onetoZero(arr);

13:     System.out.println("Number of Ones = " + numOnes);

14:     System.out.print("New values of the array: [ ");

15:     for (int i = 0; i < arr.length; i++) {

16:         System.out.print(arr[i] + " ");

17:     }

18:    System.out.println("]");

19: }
Here is the output of this program:
Values of the array: [ 1 3 4 5 1 1 7 ]

Number of Ones = 3

New values of the array: [ 0 3 4 5 0 0 7 ]
Let's go over the main() method line by line so that you can see what is going on. Lines 2 through 4 set up the initial variables for this example. The first one is an array of integers; the second one is an instance of the class PassByReference, which is stored in the variable test. The third is a simple integer to hold the number of ones in the array. Lines 6 through 11 print out the initial values of the array; you can see the output of these lines in the first line of the output. Line 12 is where the real work takes place; this is where you call the onetoZero() method, defined in the object test, and pass it the array stored in arr. This method returns the number of ones in the array, which you'll then assign to the variable numOnes. Got it so far? Line 13 prints out the number of ones, that is, the value you got back from the onetoZero() method. It returns three, as you would expect. The last bunch of lines print out the array values. Because a reference to the array object is passed to the method, changing the array inside that method changes that original copy of the array. Printing out the values in lines 14 through 18 proves this—that last line of output shows that all the 1s in the array have been changed to 0s.

Class Methods

Just as you have class and instance variables, you also have class and instance methods, and the difference between the two types of methods are analogous. Class methods are available to any instance of the class itself and can be made available to other classes. Therefore, some class methods can be used anywhere regardless of whether an instance of the class exists or not. For example, the Java class libraries include a class called Math. The Math class defines a whole set of math operations that can be used in any program or the various number types:
float root = Math.sqrt(453.0);

System.out.print("The larger of x and y is " + Math.max(x, y));
To define class methods, use the static keyword in front of the method definition, just as you would create a class variable. For example, that max class method might have a signature like this:
static int max(int arg1, int arg2) { ... }
Java supplies "wrapper" classes for each of the base types—for example, classes for Integer, Float, and Boolean. Using class methods defined in those classes, you can convert to and from objects and primitive types. For example, the parseInt() class method in the Integer class takes a string and a radix (base) and returns the value of that string as an integer:
int count = Integer.parseInt("42", 10) // returns 42
Most methods that operate on a particular object, or that affect that object, should be defined as instance methods. Methods that provide some general utility but do not directly affect an instance of that class are better declared as class methods.

Creating Java Applications

Now that you know how to create classes, objects, and class and instance variables and methods, all that's left is to put it together into something that can actually run—in other words, to create a Java application. Applications, to refresh your memory, are Java programs that run on their own. Applications are different from applets, which require HotJava or a Java-capable browser to view them. Much of what you've been creating up to this point have been Java applications; next week you'll dive into how to create applets. (Applets require a bit more background in order to get them to interact with the browser and draw and update with the graphics system. You'll learn all of this next week.) A Java application consists of one of more classes and can be as large or as small as you want it to be. HotJava is an example of a Java application. The only thing you need to make a Java application run is one class that serves as the "jumping-off" point for the rest of your Java program. If your program is small enough, it may need only the one class. The jumping-off class for your program needs one thing: a main() method. When you run your compiled Java class (using the Java interpreter), the main() method is the first thing that gets called. None of this should be much of a surprise to you at this point; you've been creating Java applications with main() methods all along. The signature for the main() method always looks like this:
public static void main(String args[]) {...}
Here's a run-down of the parts of the main() method:
  • public means that this method is available to other classes and objects. The main() method must be declared public. You'll learn more about public and private methods in Week 3.
  • static means that this is a class method.
  • void means the main() method doesn't return anything.
  • main() takes one parameter: an array of strings. This argument is used for command-line arguments, which you'll learn about in the next section.
The body of the main() method contains any code you need to get your application started: initializing variables or creating instances of any classes you may have declared. When Java executes the main() method, keep in mind that main() is a class method—the class that holds it is not automatically instantiated when your program runs. If you want to treat that class as an object, you have to instantiate it in the main() method yourself (all the examples up to this point have done this).

Java Applications and Command-Line Arguments

Because Java applications are stand-alone programs, it's useful to be able to pass arguments or options to that program to determine how the program is going to run, or to enable a generic program to operate on many different kinds of input. Command-line arguments can be used for many different purposes—for example, to turn on debugging input, to indicate a filename to read or write from, or for any other information that you might want your Java program to know.

Passing Arguments to Java Programs

To pass arguments to a Java program, you merely append them to the command line when you run your Java program:
java Myprogram argumentOne 2 three
On this command line, you have three arguments: argumentOne, the number 2, and three. Note that a space separates arguments, so this command line produces three arguments:
java myprogram Java is cool
To group arguments, surround them with double-quotes. This command line produces one argument:
java myprogram "Java is cool"
The double-quotes are stripped off before the argument gets to your Java program.

Handling Arguments in Your Java Program

How does Java handle arguments? It stores them in an array of strings, which is passed to the main() method in your Java program. Remember the signature for main():
public static void main (String args[]) {...}
Here, args is the name of the array of strings that contains the list of arguments. You can actually call it anything you want. Inside your main() method, you can then handle the arguments your program was given by iterating over the array of arguments and handling those arguments any way you want. For example, Listing 6.5 is a really simple class that prints out the arguments it gets, one per line.
    Listing 6.5. The EchoArgs class.
1: class EchoArgs {

2:     public static void main(String args[]) {

3:         for (int i = 0; i < args.length; i++) {

4:             System.out.println("Argument " + i + ": " + args[i]);

5:         }

6:     }

7: }
The following is some sample input and output from this program:
java EchoArgs 1 2 3 jump

Argument 0: 1

Argument 1: 2

Argument 2: 3

Argument 3: jump

java EchoArgs "foo bar" zap twaddle 5

Argument 0: foo bar

Argument 1: zap

Argument 2: twaddle

Argument 3: 5
Note how the arguments are grouped in the listing; putting quotes around foo bar causes that argument to be treated as one unit inside the argument array.
Technical Note: The array of arguments in Java is not analogous to argv in C and Unix. In particular, arg[0], the first element in the array of arguments, is the first command-line argument after the name of the class—not the name of the program as it would be in C. Be careful of this as you write your Java programs.
An important thing to note about the arguments you pass into a Java program is that those arguments will be stored in an array of strings. This means that any arguments you pass to your Java program are strings stored in the argument array. To treat them as non-strings, you'll have to convert them to whatever type you want them to be. For example, suppose you have a very simple Java program called SumAverage that takes any number of numeric arguments and returns the sum and the average of those arguments. Listing 6.6 shows a first pass at this program.
    Listing 6.6. First try at the SumAverage class.
 1: class SumAverage {

 2:     public static void main (String args[]) {

 3:         int sum = 0;

 4: 

 5:         for (int i = 0; i < args.length; i++) {

 6:             sum += args[i];

 7:         }

 8: 

 9:         System.out.println("Sum is: " + sum);

10:         System.out.println("Average is: " +

11:             (float)sum / args.length);

12:     }

13: }
At first glance, this program seems rather straightforward—a for loop iterates over the array of arguments, summing them, and then the sum and the average are printed out as the last step. What happens when you try and compile this? You get the following error:
SumAverage.java:9: Incompatible type for +=. Can't convert java.lang.String to int.

    sum += args[i];
You get this error because the argument array is an array of strings. Even though you passed integers into the program from the command line, those integers were converted to strings before they were stored in the array. To be able to sum those integers, you have to convert them back from strings to integers. There's a class method for the Integer class, called parseInt, that does just this. If you change line 7 to use that method, everything works just fine:
sum += Integer.parseInt(args[i]);
Now, compiling the program produces no errors and running it with various arguments returns the expected results. For example, java SumAverage 1 2 3 returns the following output:
Sum is: 6

Average is: 2

Summary

Today, you put together everything you've come across in the preceding days of this week about how to create Java classes and use them in Java applications. This included the following:
  • Instance and class variables, which hold the attributes of the class and its instances. You learned how to declare them, how they are different from regular local variables, and how to declare constants.
  • Instance and class methods, which define a class's behavior. You learned how to define methods, including the parts of a method's signature, how to return values from a method, how arguments are passed in and out of methods, and how to use the this keyword to refer to the current object
  • Java applications—all about the main() method and how it works, as well as how to pass arguments into a Java application from a command line.

Q&A

Q: I tried creating a constant variable inside a method, and I got a compiler error when I tried it. What was I doing wrong? A: You can create only constant (final) class or instance variables; local variables cannot be constant. Q: static and final are not exactly the most descriptive words for creating class variables, class methods, and constants. Why not use class and const? A: static comes from Java's C++ heritage; C++ uses the static keyword to retain memory for class variables and methods (and, in fact, they aren't called class methods and variables in C++: static member functions and variables are more common terms).

final, however, is new. final is used in a more general way for classes and methods to indicate that those things cannot be subclassed or overridden. Using the final keyword for variables is consistent with that behavior. final variables are not quite the same as constant variables in C++, which is why the const keyword is not used.

Q: In my class, I have an instance variable called name. I also have a local variable called name in a method, which, because of variable scope, gets hidden by the local variable. Is there any way to get hold of the instance variable's value? A: The easiest way is not to name your local variables the same names as your instance variables. If you feel you must, you can use this.name to refer to the instance variable and name to refer to the local variable. Q: I want to pass command-line arguments to an applet. How do I do this? A: You're writing applets already? Been skipping ahead, have you? The answer is that you use HTML attributes to pass arguments to an applet, not the command line (you don't have a command line for applets). You'll learn how to do this next week. Q: I wrote a program to take four arguments, but if I give it too few arguments, it crashes with a run-time error. A: Testing for the number and type of arguments your program expects is up to you in your Java program; Java won't do it for you. If your program requires four arguments, test that you have indeed been given four arguments, and return an error message if you haven't