Red Hat Linux 9 Professional Secrets [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Red Hat Linux 9 Professional Secrets [Electronic resources] - نسخه متنی

Naba Barkakati

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








Learning Java



Now that you have seen some examples of Java programming, this section provides an overview of Java. Previous examples show that Java can be used to create both standalone applications and applets that can be embedded in an HTML document. As you learn the features of Java, you'll notice that Java has everything you need from a general-purpose programming language. Although Java has been associated mostly with the creation of applets to be embedded in Web pages, many people have come to realize that Java is also ideal for developing general-purpose applications. Nowadays, Java is also extensively used for server-side programs such as Java servlets that work with Web servers.

One of the reasons for Java's popularity is the portability of Java code. The compiled Java code runs on any system for which a Java interpreter and the Java libraries are available. It's not trivial to build the Java libraries, but once the Java interpreter and libraries are available on an operating system, you can run most Java applications unchanged on that system.


Objects in Java


Java is an object-oriented language. So much so that Java does not allow any standalone procedures at all; all data and procedures must be inside an object. In fact, the entire Java application is an object as well.

The basic concepts of object-based programming are the same as those of other object-oriented programming languages such as Smalltalk or C++. There are three underlying concepts:



  • Data abstraction



  • Inheritance



  • Polymorphism




Data Abstraction


To understand data abstraction, consider the file input/output (I/O) routines in the C run-time library. These routines allow you to view the file as a stream of bytes and allow you to perform various operations on this stream by calling the file I/O routines. For example, you can call

fopen to open a file,

fclose to close it,

fgetc to read a character from it, and

fputc to write a character to it. This abstract model of a file is implemented by defining a data type named

FILE to hold all relevant information about a file. The C constructs

struct and

typedef are used to define

FILE . You can think of this definition of

FILE , together with the functions that operate on it, as a new data type just like C's

int or

char .

To use the

FILE data type in C, you do not have to know the data structure that defines it. In fact, the underlying data structure of

FILE can vary from one system to another. Yet, the C file I/O routines work in the same manner on all systems. This is possible because you never access the members of the

FILE data structure directly. Instead you rely on functions and macros that essentially hide the inner details of

FILE . This is known as data hiding.

Data abstraction is the process of defining a data type, often called an abstract data type (ADT), together with the principle of data hiding. The definition of an ADT involves specifying the internal representation of the ADT's data as well as the functions to be used by others to manipulate the ADT. Data hiding is used to ensure that the the internal structure of the ADT can be altered without any fear of breaking the programs that call the functions that are provided for operations on that ADT. Thus, C's

FILE data type is an example of an ADT (see Figure 26-2).


Figure 26-2: C's FILE Type as an Example of Abstract Data Type (ADT).

In object-oriented languages, you create an object from an ADT. Essentially, an ADT is a collection of variables together with the procedures necessary to operate on those variables. The variables represent the information contained in the object while the procedures define the operations that can be performed on that object. You can think of the ADT as a template from which specific instances of objects can be created as needed. The term class is often used for this template, consequently class is synonymous with an ADT. In fact, Java provides the class keyword precisely for the purpose of defining an ADT-the template from which objects are created. The ADT is a template for objects in the sense that creating an object involves setting aside a block of memory for the variables of that object.

In Java, the procedures that operate on an object are known as methods. This term comes from the object-oriented language Smalltalk. The methods define the behavior of an object. Another common term of object-oriented programming also originated in Smalltalk-the idea of sending messages to an object causing it to perform an operation by invoking one of the methods. In Java, you do this is by calling the appropriate method of the object.

In Java, you use the

class keyword to define the blueprint of an object. That means a class defines the data and methods that constitute a type of object. Then, you can create instances of the object by using the new keyword. For example, you might create an instance of a

Circle class as follows:

Circle c1 = new Circle(100.0, 60.0, 50.0);

This example invokes the

Circle class constructor that accepts three floating-point numbers as argument (presumably, the coordinates of the center and the radius of the circle). You'll see a complete example of classes in the 'Geometric Shapes in Java' section, later in this chapter.


Inheritance


Data abstraction does not cover an important characteristic of objects. Real-world objects do not exist in isolation. Each object is related to one or more other objects. In fact, you can often describe a new kind of object by pointing out how the new object's characteristics and behavior differ from those of a class of objects that already exists. This is what you do when you describe an object with a sentence such as: B is just like A, except that B has ... and B does ... . Here you are defining objects of type B in terms of those of type A.

This notion of defining a new object in terms of an old one is an integral part of object-oriented programming. The term inheritance is used for this concept because you can think of one class of objects as inheriting the data and behavior from another class. Inheritance imposes a hierarchical relationship among classes where a child class inherits from its parent. In Java terminology, the parent class is known as the superclass; the child is the subclass. In a Java program, you use the

extends keyword to indicate that one class is a subclass of another.






Insider Insight

Unlike C++, Java does not support multiple inheritance (multiple inheritance allows a class to inherit from multiple superclasses). Java allows a class to have only one superclass. In Java, all classes inherit from a single root class named

Object . (The Smalltalk programming language also provides a class hierarchy of this type). Here the term root class refers to a class that does not have any superclass.



Polymorphism


In a literal sense, polymorphism means the quality of having more than one form. In the context of object-oriented programming, polymorphism refers to the fact that a single operation can have different behavior in different objects. In other words, different objects react differently to the same message. For example, consider the operation of addition. For two numbers, addition should generate the sum. In a programming language that supports object-oriented programming, you should be able to express the operation of addition by an operator, say,

+ . When this is possible, you can use the expression

x+y to denote the sum of

x and

y , for many different types of

x and

y : integers, floating-point numbers, and, even strings (for strings the

+ operation means the concatenation of two strings).

Similarly, suppose a number of geometrical shapes all support a method,

draw . Each object reacts to this method by displaying its shape on a display screen. Obviously, the actual mechanism for displaying the object differs from one shape to another, but all shapes perform this task in response to the same method.

Polymorphism helps by allowing you to simplify the syntax of performing the same operation on a collection of objects. For example, by exploiting polymorphism, you can compute the area of each geometrical shape in an array of shapes with a simple loop like this:

// Assume "shapes" is an array of shapes (rectangles, circles,   
// etc.) and "computeArea" is a function that computes the
// area of a shape.
for(int i=0; i < shapes.length; i++)
{
double area = shapes[i].computeArea();
System.out.println("Area = "+area);
}

This is possible because regardless of the exact geometrical shape, each object supports the

computeArea method and computes the area in a way appropriate for that shape.


Geometric Shapes in Java: An Example


For a concrete illustration of object-oriented programming in Java, consider the following example. Suppose that you want to write a computer program that handles geometric shapes such as rectangles and circles. The program should be able to draw any shape and compute its area.


Shape Class

The first step in implementing the geometric shapes in Java is to define the classes. I'll start with an abstract class that simply defines the behavior of the shape classes by defining the common methods. The following listing shows the abstract

Shape class, which you should save in the

Shape.java file:

//---------------------------------------------------------------
// File: Shape.java
//
// Abstract class for Shape objects
abstract public class Shape
{
abstract public void draw();
abstract public double computeArea();
}

As this listing shows, you use the

abstract keyword to indicate that a class cannot be instantiated because it does not implement all the methods.





Caution

If you know C++, you'll notice some superficial similarities between C++ and Java class definitions. Note, however, that the similarities are really superficial. As an experienced C++ programmer, I would say that you'll be better off if you approach Java as a brand-new object-oriented language rather than as a mutation of C++. You can still use your knowledge of C syntax, but when it comes to the object-oriented features of Java, you should not try to extrapolate from your knowledge of C++.



Circle Class

After you define the abstract

Shape class, you can create concrete versions of

Shape classes such as a

Circle and

Rectangle . Here is a simple implementation of the

Circle class that you should save in a file named

Circle.java :

//---------------------------------------------------------------
// File: Circle.java
//
// Circle class

public class Circle extends Shape
{
double x, y;
double radius;
public Circle(double x, double y, double r)
{
this.x = x;
this.y = y;
this.radius = r;
}
public double computeArea()
{
return Math.PI * radius * radius;
}
public void draw()
{
System.out.println("Circle of radius "+radius+
" at ("+x+", "+y+")");
}
}

As this definition of the

Circle class shows, this shape class implements the

computeArea and

draw methods that were declared as abstract in the

Shape class. The

Circle class also defines three

double variables-

x ,

y , and

radius -that denote the coordinates of the center and the radius of the circle. Such variables are referred to as instance variables of the class.

The

extends keyword in the

Circle class definition indicates that

Circle is a subclass of the

Shape class. The

public qualifier specifies that the

Circle class is accessible from other packages (in Java, a package is a collection of classes).


Rectangle Class

Following the pattern of the

Circle class, I defined the

Rectangle class as shown in the following listing:

//---------------------------------------------------------------
// File: Rectangle.java
//
// Rectangle class
public class Rectangle extends Shape
{
double x1, y1;
double x2, y2;
public Rectangle(double x1, double y1,
double x2, double y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public double computeArea()
{
return Math.abs((x1-x2)*(y1-y2));
}
public void draw()
{
System.out.println("Rectangle with corners "+
"("+x1+", "+y1+") and "+
"("+x2+", "+y2+")");
}
}

Just as the

Circle class is saved in the

Circle.java file, the

Rectangle class should be saved in the

Rectangle.java file-at least that's how Sun's Java 2 SDK expects the class definitions.






Insider Insight

The

computeArea method of the

Rectangle class calls the

Math.abs method to get the absolute value of an argument. Although this looks like the invocation of an object's method, there is no object named

Math; instead

Math is the name of a class. The

abs method is a static method in the

Math class. You can invoke a static method without having to create an instance of the class.



MakeShape Class-The Test Program

Now that I have defined the

Circle and

Rectangle classes, it's time to test them with a simple program. In Java, the program itself must be another class, and for a standalone Java program, the class must include a

public static void method called

main (this is akin to the main function in a C program).

The following listing shows the

MakeShape class (in a file named

MakeShape.java ) that includes a

main method to test the geometric shapes:

 //---------------------------------------------------------------
// File: MakeShape.java
//
// Java application to try out various shapes
public class MakeShape
{
public static void main(String args[])
{
Shape shapes[] = new Shape[2];
shapes[0] = new Circle(100.0, 100.0, 50.0);
shapes[1] = new Rectangle(80., 40., 120., 60.);

System.out.println("\n"+shapes.length+" shapes\n");
for(int i=0; i < shapes.length; i++)
{
double area = shapes[i].computeArea();
System.out.println("Shape #"+i);
shapes[i].draw();
System.out.println("Area = "+area);
System.out.println("-----------");
}
}
}

The

main method creates an array of

Shape objects and initializes the array with different shapes. Then, the

computeArea and

draw methods of each shape are invoked.






Insider Insight

You use the

new keyword to create instances of objects in Java. There is no corresponding

delete or

free keyword to get rid of objects when you no longer need them. Instead, Java supports a technique called garbage collection to automatically destroy objects that are no longer needed (Java keeps track of all references to an object and removes the object when there are no more references to it). That means you never have to worry about freeing memory in Java. Because memory management is a source of many errors in C and C++ programs, Java's support for garbage collection helps eliminate a major source of potential errors in your applications.


In this example, the

MakeShape class is the Java application. To compile the program, type the following command:

javac MakeShape.java

This step takes care of compiling the

MakeShape.java file and all the related classes (the

Shape.java ,

Circle.java , and

Rectangle.java files). In other words, the Java compiler (javac) acts a bit like the make utility in UNIX-

javac determines the dependencies among classes and compiles all necessary classes.

To run the

MakeShape program, use the Java interpreter, as follows:

java MakeShape

The following listing shows the result of running the

MakeShape program in a terminal window in Red Hat Linux:

2 shapes
Shape #0
Circle of radius 50.0 at (100.0, 100.0)
Area = 7853.981633974483
-----------
Shape #1
Rectangle with corners (80.0, 40.0) and (120.0, 60.0)
Area = 800.0
-----------


Java Program Structure


A Java program consists of one or more classes. For standalone applications, you must have a class with a

public void static main method. Applets require only a subclass of the

Applet class.

The Java 2 SDK expects the source files to have the same name as the class, but with a

.java extension (thus, a class named

Circle is defined in the file

Circle.java ). However, other Java development environments may have a different convention for naming files.

Within each source file, the parts of the program are laid out in the following manner:



  1. The file starts with some comments that describe the purpose of the class and provide other pertinent information such as the name of author and revision dates. Java supports both C and C++-style comments. As in ANSI C, comments may start with a

    /* and end after a

    */ pair. Or, you may simply begin a line of comment with a pair of slashes (

    // ). A special type of comment, known as doc comment, begins with a

    /** and ends with

    */ . The doc comments can be extracted by the

    javadoc utility program to create online documentation for classes.



  2. One or more

    import statements that allow you to use abbreviated class names. For example, if you use the

    java.applet.Applet class, you can refer to that class by the short name

    Applet provided you include the following

    import statement in the source file:

    import java.applet.*;

    Note that the

    import statement does not really bring in any extra code into a class; it's simply a way to save typing so you can refer to a class by a shorter name (for example,

    Applet instead of

    java.applet.Applet ).



  3. The class definition that includes instance variables and methods. All variables and methods must be inside the class definition.




Primitive Data Types in Java


Java supports the standard C data types of

char ,

short ,

int ,

long ,

float , and

double . Additionally, Java introduces the byte and boolean types. Unlike C, however, Java also specifies the exact size of all primitive data types (in C, the size of the

int type varies from one system to another). Table 26-2 summarizes Java's primitive types.




































Table 26-2: Java's Primitive Data Types


Type


Description


boolean


A 1-bit value that contains

true or

false . A

boolean value is not an integer.


byte


An 8-bit signed integer with values between -128 and 127


char


A 16-bit unsigned integer value representing a Unicode character (Unicode is a character encoding system designed to support storage and processing of written texts of many diverse languages). You can initialize a

char variable with the notation

\u

xxxx , where

xxxx is a sequence of hexadecimal digits (for example,

char c = \u00ff; ).


double


A 64-bit, double-precision floating-point value in the IEEE 754 format (a standard format that expresses a floating-point number in binary format)


float


A 32-bit, single-precision floating-point value in IEEE 754 format


int


A 32-bit signed integer with values between -2,147,483,648 and 2,147,483,647.


long


A 64-bit signed integer with values between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807.


short


A 16-bit signed integer with values between -32,768 and 32,767.


Although most of the primitive types should be familiar to C programmers, the following C-style usage are not allowed in Java:



  • There is no

    unsigned keyword in Java; all integer values are signed.



  • You cannot write

    short int or

    long int (these combinations are often used in C programs).




Nonprimitive Data Types in Java


The nonprimitive data types in Java are objects and arrays. All nonprimitive types are handled by reference-that means when you pass a nonprimitive type to a method, the address of the object is passed to the method. The primitive types, however, are passed by value-that means a copy of the data is passed to the method.








Secret


Unlike C, Java does not have any pointer type. So, you cannot work with addresses of variables with the &,

* , and

- > operators. By eliminating pointers, Java gets rid of a common source of bugs and also prevents programmers from performing tricks with pointers that bypass Java's security mechanisms.

Instead of pointers, you have to work with references to objects (a reference is the address of an object). You need to understand the following implications of the fact that you have to handle objects through references:



  • When you assign one object to another, Java does not actually copy the value of the object. All that happens is that you end up with two references to the same object. Consider the following example:

        Circle c1 = new Circle(0., 0., 20.);
    Circle c2 = new Circle(100.0, 60.0, 20.0);
    c1 = c2; // c1 now refers to the same Circle as does c2.

    Here, both

    c1 and

    c2 end up referring to the same

    Circle object. The

    Circle object that

    c1 originally referred to is lost after you assign

    c2 to

    c1 . (The Java garbage collector automatically reclaims the memory allocated to the lost object.)



  • To actually copy an object's value into another, you have to call the

    clone method of the object (this assumes that the object supports the

    clone method). Here is an example:

        Vector x = new Vector();
    Vector y = x.clone(); // Vector y is a copy of Vector x.



  • When you use the

    == operator, you check whether two variables refer to the same object. In other words, the

    == operator checks whether two objects are identical. To check if two separate objects contain the same value, you must use a special method for that object type. For example, many Java classes provide an

    equals method to check for equality of object values.














String Type


Java includes a built-in

String type, and the compiler treats a

String almost like a primitive type. Java's

String class is a part of the

java.lang package, which the Java compiler uses by default.

The Java compiler automatically converts text within double quotes (

"..." ) into a

String . Also, the

+ operator concatenates

String objects. For example, you can write code such as the following:

String welcome = "Welcome to " + "Java.";
int numchars = welcome.length();
System.out.println("There are "+numchars+
" characters in: "+welcome);

When executed, this code prints the following:

There are 16 characters in: Welcome to Java.

The

String class supports a number of other methods that provide the functionality of the C's string manipulation functions (that are defined in the C header file <

string.h >). Java includes two related classes for handling text strings:



  • String to hold a string of characters that cannot be individually manipulated (in other words, you cannot insert or replace characters in the string).



  • StringBuffer to represent a string of characters that may be manipulated as necessary. You can append, insert, and replace characters in a

    StringBuffer object.



Table 26-3 summarizes the methods of the

String class.





























































































Table 26-3: Methods of the String Class


Method


Description


char charAt(int index);


Returns character at a specified index


int compareTo(String s);


Compares this

String with another

String s


String concat(String s);


Concatenates this

String with another

String


String copyValueOf(char[] ca);


Returns a

String equivalent to the specified array of

characters. This is a static method of the

String class.


boolean endsWith (String suffix);


Returns

true if

String ends with suffix



boolean equals(String s);


Returns

true if this

String matches another

String s (case-sensitive comparison)


boolean equalsIgnoreCase s

(String s);


Returns

true if this

String matches another

String regardless of case (case-insensitive comparison)


byte[] getBytes();


Copies characters from a

String into a new

byte array (uses the default character-encoding of the system)


byte[] getBytes(String encodingName);


Copies characters from a

String into a new

byte array according to the character encoding specified by a name such as US-ASCII, ISO-8859-1, UTF-8, UTF-16, and so on


void getChars(int srcBegin, int srcEnd, char[] dest, int destBegin);


Copies characters from a

String into a

char array



int hashcode();


Returns hash code for the

String


int indexOf(int c);


Returns index of first occurrence of a character


int indexOf(String s);


Returns index of first occurrence of

String s in the current

String


String intern();


Returns a unique instance of

String from a global shared pool of

String objects


int lastIndexOf(int c);


Returns index of the last occurrence of a character


int lastIndexOf(String s);


Returns index of last occurrence of

String s in the current

String


int length();


Returns the length of the

String (the number of characters in the

string )


boolean regionMatches (int offset, String s, String s int soffset, int length);


Returns true if a region of the

String matches the specified region of another


String replace(char old, char new);


Replaces all occurrences of old character with new



boolean startsWith (String prefix);


Returns true if

String starts with specified prefix



String substring(int begin, int end);


Returns a substring of this

String


char[] toCharArray();


Returns a character array from the

String


String toLowerCase();


Converts

String to lowercase


String toString();


Returns another

String with the same contents


String toUpperCase();


Converts

String to uppercase


String trim();


Removes any leading and trailing white space from

String


String valueOf(type obj);


Returns the

String representation of an object's value (type may be any object of primitive type such as

boolean ,

char ,

int ,

long ,

float , and

double ). This is a static method of the

String class.







Insider Insight

The

String class is defined with a

final keyword. That means you cannot subclass

String . The Java compiler can optimize a final class so that the class can be used as efficiently as possible. To declare a class as

final , use the following syntax:

public final class ClassName extends SuperClassName
{
// Body of class
}



Arrays in Java


An array is an ordered collection of one or more elements. Java supports arrays of all primitive as well as nonprimitive data types. As in C, you can declare an array variable by appending square brackets to the variable name, as follows:

byte buffer[] = new byte[256]; // Create an array for 256 byte variables.
Shape shapes[] = new Shape[10]; // Create an array to hold 10 Shape objects.








Secret


In Java creating an array for a specific type of object does not actually create the objects that are stored in the array. All that Java creates is an array capable of holding references to objects of a specified type. All array elements are initialized with the value

null (which is a Java keyword that means a variable that does not refer to any object). You must individually create the objects that you want to store in the array.

Here is how you might create and initialize an array of

String objects:

String language[] = new String[4];
language[0] = "C";
language[1] = "C++";
language[2] = "Java";
// language[3] == null (the default value)

As this example illustrates, you access array elements the same way you use arrays in C-by putting an integer-values expression within square brackets after the array's name. The array indexes start at 0.

You can always get the length of an array-the number of elements the array can hold-by accessing the length instance variable of the array. Here is an example:

String names[] = new String[5];
int len = names.length; // len = 5












Exception-Handling in Java


Exceptions refer to unusual conditions in a program. They can be outright errors that cause the program to fail or conditions that can lead to errors. Typically, you can always detect when certain types of errors are about to occur. For instance, when indexing an array with the

[] operator, you could detect if the index is beyond the range of valid values. Although you could check for such an error, it's tedious to check for errors whenever you index into an array. Java's exception-handling mechanism allows you to place the exception-handling code in one place and avoid having to check for errors all over your program.








Secret


Java's exception-handling mechanism is similar to that in C++. The basic features are as follows:



  • When a block of code generates an error, it uses the

    throw keyword to throw an exception. When an exception is thrown, the Java interpreter stops executing that block of code and transfers control to a block that is designated as the handler for that exception (there are many types of exceptions).



  • Enclose inside a

    try block any code that may throw an exception.



  • Immediately following the

    try block, place one or more

    catch blocks that handle specific exceptions thrown by the code inside the

    try block.



  • Inside a

    finally block place any code that should be executed to clean up before exiting the

    try block (regardless of whether there is an exception or not). In the

    finally block, you may include code to close files and network connections before the program exits.













The following code fragment illustrates the syntax of

try ,

catch , and

finally blocks in Java:

try
{
// Code that may generate exceptions of type AnException and
// AnotherException
}
catch(AnException e1)
{
// Handle exception of type AnException
}
catch(AnotherException e2)
{
// Handle exception of type AnotherException
}
finally
{
// This block of code is always executed after exiting the try block
// regardless of how the try block exits.
}


Interfaces


Java does not support multiple inheritance, so each class can have only one superclass. However, sometimes you may want to inherit other types of behavior. For example, you may want to support a specific set of methods in a class (this is akin to saying that your class can do x, y, and z). Java provides the interface keyword that allows a class to implement a specific set of capabilities.

An interface looks like an abstract class declaration. For example, the

run method is used by the

Thread class (see the 'Threads' section) to start a thread of execution in a Java program. The

Runnable interface specifies this capability through the following interface declaration:

public interface Runnable
{
public abstract void run();
}

If you implement all the methods of an interface, you can declare this fact by using the

implements keyword in the class definition. For example, if a class defines the

run method (which constitutes the

Runnable interface), the class definition specifies this fact as follows:

import java.applet.*;
public class MyApplet extends Applet implements Runnable
{
// Must include the run() method
public void run()
{
// This can be the body of a thread.
}
// Other methods of the class
// ...
}


Threads in Java


Java includes built-in support for threads. A thread refers to a single flow of control-a single sequence of Java byte codes being executed by the Java Virtual Machine. Just as an operating system can execute multiple processes (by allocating short intervals of processor time to each process in turn), the Java Virtual Machine can execute multiple threads within a single application. You can think of threads as 'multitasking within a single process.'








Secret


Threads can be very useful because you can turn individual threads loose on different sets of tasks. For example, one thread might monitor all user inputs to an applet, while another thread periodically updates the display. The problem with threads is that they all share the same set of variables within the program. That means, each thread must be careful when accessing and updating any variable. As a thread changes parts of an object, it may lose its time slice and another may become active and use the partially updated object. Java includes the

synchronized keyword that allows you to mark objects and methods that should not be accessed simultaneously by multiple threads. For example, you'd write the following code to ensure that a thread acquires a lock on

myObject before executing the statements within the curly braces (

{...} ):

synchronized(myObject)
{
// Some task that needs to be synchronized among threads
// ...
}












Using Threads in an Applet


The best way to understand threads is to go through a simple example. The following listing shows the

DigitalClock applet that uses a thread to display the current date and time:

//---------------------------------------------------------------
// File: DigitalClock.java
//
// Displays a digital clock using a thread.
import java.util.*;
import java.awt.*;
import java.applet.*;
public class DigitalClock extends Applet implements Runnable
{
private volatile Thread clockThread;
int interval = 1000;
// The run method is required by the Runnable interface.
public void run()
{
Thread curThread = Thread.currentThread();
while(curThread == clockThread)
{
try
{
curThread.sleep(interval);
}
catch(InterruptedException e) {}
// Repaint the clock.
repaint();
}
}
public void start()
{
// Create and start the clock thread.
clockThread = new Thread(this);
clockThread.start();
}
public void stop()
{
// Get rid of the clock thread.
clockThread = null;
}
// The paint method displays the date and time.
public void paint(Graphics gc)
{
Font helv = new Font("Helvetica", Font.ITALIC, 16);
gc.setFont(helv);
gc.drawString(new Date().toString(), 4, 20);
}
}

Save this listing in the

DigitalClock.java file and compile the applet with the following command:

javac DigitalClock.java

Next, create an HTML document,

DigitalClockl , and embed the applet as follows:

<html>
<body>
<applet width=200 height=24 code=DigitalClock>
A Java clock applet.
</applet>
</body>
</html>

Now, type the following command to run the applet using the

appletviewer :

appletviewer DigitalClockl

Figure 26-3 shows the resulting appletviewer window with the output from the Clock applet.


Figure 26-3: Running the Clock Applet in the

appletviewer .

As the applet runs, it should update the clock display every second.


Understanding Thread Usage in an Applet


After you have seen the

DigitalClock applet in action, you should go through its listing to see how a thread works. When going through the

DigitalClock applet's code, you should note the following:



  • To create a thread, you need an instance of a class that implements the

    Runnable interface. Typically, you would implement the

    Runnable interface in your applet by providing a

    run method. Then, you can create the

    Thread object by calling its constructor as follows:

    myThread = Thread(this);



  • The Java Virtual Machine (JVM) calls the

    start method of the applet when the applet should run and the JVM calls the

    stop method when the applet should stop running. Thus, the applet's

    start method is a good place to create the

    Thread object.



  • After you create the

    Thread object, you must call that

    Thread object's

    start method (note that this is different from the

    start method of the applet) to start running the thread.



  • When started, the

    Thread executes the body of the

    run method. Thus, the

    run method should include code to perform whatever task you want the thread to perform.



  • When you want to stop the thread, set the Thread's reference to null, as follows:

    myThread = null;

    The Java garbage collection mechanism would clean up the

    Thread at an appropriate time.




/ 341