An Overview of Java - Tools and Programming - UNIX: The Complete Reference (2007)

UNIX: The Complete Reference (2007)

Part V: Tools and Programming

Chapter 25: An Overview of Java

Java is a powerful object-oriented programming language, developed at Sun Microsystems in the mid 1990s. One of its primary strengths is that it enables you to develop programs that are platform independent, meaning that they can be run on any system that supports Java. This includes Microsoft Windows, Mac OS X, all major versions of UNIX (including Linux, Solaris, and FreeBSD), and various other systems. At the time of this writing, Sun has recently announced plans to make Java open source. This is likely to encourage more system distributions to include Java components by default, making Java even more easily portable.

In general, Java is very similar to C++, but it is easier to use, sometimes at the cost of performance. Java has a much larger set of built-in standard libraries than C++. It is suitable for large-scale development projects as well as small applets that can be run in a web browsers. Java uses automatic garbage collection for memory management. This is a convenient feature of the language that reduces bugs and speeds development; however, it can be slower than the C/C++ style of memory management. Java also replaces some of the most complex and obscure features of C++, such as pointers, again for the purpose of making Java programs less prone to bugs. One of the biggest differences between Java and C++ is that Java programs are compiled to bytecode, which is run in a virtual machine. This makes it much more portable than C++, but again, it slows performance.

This chapter provides a brief introduction to some of the basics of the Java language and its associated class libraries.

Object-Oriented Programming

Java is an object-oriented programming language. You are probably familiar with procedural programming languages in which statements are executed in order, line by line, and may be grouped into procedures that are called from the main body of code. Object-oriented programming is a new way of thinking about the structure of your program. Instead of just grouping statements into procedures, statements and procedures (called methods) are grouped into classes. To use a class, you create an instance of the class called an object. A class is like a type definition for an object.

For example, suppose you are writing a system to keep track of students enrolled at a university You might create a class called StudentFile. It would include variables such as name and IDnum. It would also include methods such as SetStudentData and GetStudentID.

When you wanted to add a new student to the system, you would create a new StudentFile object. You would use the SetStudentData method of this object to save the student’s name and ID number in the appropriate variables, and the GetStudentID method to retrieve the ID number when you needed it.

Bytecode and the Java Virtual Machine (JVM)

A Java source file is compiled to generate one or more .class files. These contain bytecode. Bytecode is a set of instructions that can be interpreted by a Java Virtual Machine (JVM). Many systems come with a JVM installed by default. The JVM can also be downloaded from the Sun web site, http://java.sun.com/.

The key to Java’s platform independence is that the same bytecode can be interpreted by JVMs on any hardware platform. This allows you to compile a Java program into bytecode on a UNIX system, for example, and then use a JVM on a Windows machine to run the program from the bytecode. Since JVM implementations are available for virtually all modern systems, Java programs are highly portable.

It is possible to find software that compiles Java programs directly into native executables. Although this allows for faster performance, these executables are platform-specific and cannot be run on other systems.

Applications and Applets

There are two types of Java programs: applications and applets. An application is executed by a JVM running directly on the system. An applet is typically executed by a web browser. The browser contains a JVM and also provides the environment in which the applet runs.

When a user opens a web page containing a reference to an applet, the applet is downloaded to a user’s machine. It is essential to restrict the capabilities of these applets. If, for example, an applet can read and write files on the local machine, it can accidentally or deliberately corrupt or erase important information. Therefore, applets execute within a “sandbox.” They are blocked from reading and writing files. Other restrictions also apply This is an important part of the Java security architecture.

It is possible to associate a digital signature with an applet. This indicates that the applet was developed by a specific individual or organization. A user can configure his or her browser to trust applets from certain sources. The constraints of the “sandbox” can then be relaxed for these programs.

The Java Development Kit (JDK)

The Java Development Kit (JDK) contains everything you need to develop and execute Java applications and applets. If you are using Linux, Solaris, or Windows, the JDK can be downloaded, free of charge, from the Sun Microsystems web site http://java.sun.com, which also has installation instructions for each of those systems. If you are using FreeBSD, a port of the JDK is available on the web at http://www.freebsd.org/java/. Mac OS X comes with the JDK preinstalled. This chapter was written using the J2SE 5.0 JDK, but almost all of it should be relevant to other versions of Java.

The JDK includes a JVM, as well as a compiler for creating bytecode. Other tools included in the JDK are an interpreter, an applet viewer, and a documentation generator. The Java class libraries are also part of the JDK. These provide a wealth of functionality you can leverage when creating your own Java programs.

A Simple Java Application

The following steps describe how to create, compile, and execute a simple Java application. The sample application will be called Hello. When you run it, it will print the string “Hello, world”.

Create the Source File

You can use any text editor to create your source files. Start with a new file named Hello.java, and copy the following lines into the file:

class Hello{

public static void main (String args []) {

System.out.println("Hello, world");

}

}

The first line in this code declares a class named Hello.

The second line declares a method named main() in that class. The method accepts an array of String objects as its argument. Three keywords precede the method name. The public keyword indicates that the method can be invoked by code in any other class. The static keyword indicates that the method is associated with the class, not a specific instance of the class. The void keyword indicates the method does not return a value. All Java applications begin execution with the method main().

The third line displays the string “Hello, world”. This is done by invoking the method named println() in the object System.out. The method accepts one argument, a string, and sends its output to standard output. println() automatically appends a newline to its output. (There is also a method named print() that does not append a newline.)

Note that, as in C/C++, Java uses curly braces to group blocks of code, and semicolons to end statements.

Compile the Source File

You must now compile your file. The Java compiler included in the JDK is called javac. Enter the following command to compile Hello.java:

javac Hello.java

If you get a “javac: command not found” error, the directory with javac might not be in your path. Check to make sure that you have installed the JDK, and that you have added the directory containing javac to your path. On some systems, this directory is in /usr/java.

If all goes well, javac will create a file named Hello.class in the current directory Hello.class contains the bytecode for your application.

Invoke the Java Interpreter

You can execute a Java application by invoking the Java interpreter, which is the command java. The java interpreter uses a JVM to run the bytecode in your .class file.

To run the bytecode in Hello.class, enter the following command line:

java Hello

Note that you do not enter the extension .class. The program will generate the following output:

Hello, world

If you have more than one class definition in your .java file, the compiler will generate multiple .class files. In this case, you must run the one that contains the main() method.

The Eclipse IDE

Eclipse is an open-source project that is primarily known for providing an IDE (integrated development environment) for Java called JDT (Java Development Tools). This allows you to develop Java applications in a graphical environment. The IDE includes an editor for writing your applications and a compiler and debugger for running them. You can see an animated demo of the Eclipse IDE for Java at http://www.eclipse.org/jdt/ui/screenCasts/JavaEditor_J2SE50.htm. You can download the Eclipse SDK, including the JDT, at http://www.eclipse.org/downloads/. The Eclipse SDK runs on Linux, Solaris, Windows, and Mac OS X, among other systems.

In order to use Eclipse, you will need to have the JDK from Sun already installed. The directory with java and javac must be in your path. You can test that it is in your path by trying to run java -version. On some systems, this directory may be in /usr/java.

When you first run the SDK, you will see an introduction, several tutorials, and some samples to help you learn how to use the Java IDE. For the most part, using the graphical environment for Java development is fairly intuitive, especially if you have used an IDE such as SlickEdit or Microsoft Visual Studio.

The Java Language

This section introduces the most important features of the Java language. As you learn Java, you will notice many similarities with other modern object-oriented languages, most notably C++. If you have never done any object-oriented programming but are familiar with C, you will still notice similarities in the syntax.

Comments

As with other programming languages, you are encouraged to include comments in your source file to explain the operation of your code. Java permits three types of comments, two of which may be familiar from other languages. A single-line comment begins with //, which causes Java to ignore the remaining characters on the same line. A multiline comment begins with /* and causes Java to ignore any following text, including newlines, until the character sequence */ ends the comment.

A documentation comment is similar to a multiline comment, except that it begins with the three-character sequence /**. The JDK includes a tool named javadoc that can create documentation for your program by extracting these comments from your source files.

Simple Types

Table 25–1 summarizes the simple types defined by Java.

Table 25–1: Java Simple Types

Type

Description

byte

8-bit signed integer

short

16-bit signed integer

int

32-bit signed integer

long

64-bit signed integer

char

16-bit Unicode character

float

32-bit single-precision floating-point number

double

64-bit double-precision floating-point number

boolean

true or false

To declare a variable of one of these types, use the following syntax:

type varName;

The variable may be declared and initialized in one line:

type varName = value;

Here, type is the type of the variable and varName is its name. The value of the variable is given by value. The keyword final makes a variable into a constant, as in

final double pi = 3.14159265358979;

The following program illustrates how to declare and initialize variables of each simple type:

class SimpleTypes{

public static void main (String args []) {

byte b = 3;

short s = 300;

int i = 300000;

long 1 = 2000000000;

char c = ;A';

float f = −3.4f;

double d = 5.6E-10;

boolean bool = false;

}

}

Note that Java does not support strings as a simple type. Instead, it provides a String class in the package java.lang. Packages in general, and this class in particular, will be covered later in this chapter.

Arrays

You can create arrays of simple types (or of objects) by declaring a variable name with square brackets:

int ArrayOf Integers[] = new int [10];

This will create an array of ten integers, with indices from 0 to 9. You can use and assign elements of an array just as you would any other variable:

ArrayOf Integers[3] = 4;

System.out.println("The fourth element in the array is " + ArrayOf Integers[3]);

Operators

Java provides most of the operators found in C. As in C, the=operator is used for assignment. The operators +, −, *, and / are used for addition, subtraction, multiplication, and division, respectively Java also includes the operator % for modular division. Each of these operators can be combined with =. For example,

int i = 5;

i * = 2;

System.out.println(i);}

would print the number 10. The operator ++ increments a variable by 1 (same as +=1), and -- decrements by 1. Parentheses can be used for grouping.

Table 25–2 shows the relational and logical operators in Java. Note that, unlike C, Java uses & and | for the logical AND and OR operations. Java always evaluates both arguments to these operators. The C-style && and || operators “short-circuit,” meaning that when possible they only evaluate the first argument. Java also supports bitwise operators, although they will not be discussed here.

Table 25–2: Relational and Logical Operators

Operator

Description

Operator

Description

==

is equal to

&

AND

!=

does not equal

|

OR

>

is greater than

!

NOT

<

is less than

^

exclusive OR

>=

is greater than or equal to

&&

AND (short circuit)

<=

is less than or equal to

||

OR (short circuit)

The ternary operator is can be used in Java as shown:

expr1 ? expr2 : expr3

In this statement, expr1 can be any Boolean expression. If expr1 is true, expr2 is evaluated and returned. Otherwise, expr3 is evaluated and returned. You can use this operator for assignment; for example,

int largest = x > y ? x : y;

which assigns the greater of x and y to the variable largest.

Control Statements

Java provides the same control statements found in C/C++: if, for, while, do, and switch.

The if statement has the general form shown here:

if(expr) {

// statement block

} else {

// statement block

}

Here, expr is an expression. The first statement block is executed if expr is true. Otherwise, the second statement block is executed. The else clause and second block are optional.

You can chain together multiple if statements when there are many cases you wish to test for. Here is an example of several combined if statements:

if (x > 0 && y > 0){

System.out.println("First Quadrant");

} else if (y > 0) {

System.out.println("Second Quadrant");

} else if (x > 0) {

System.out.println("Fourth Quadrant");

} else {

System.out.println("Third Quadrant");

}

A for loop has the general form shown here:

for(initialization, test, increment) {

// statement block

}

Here, the initialization is executed only when the for loop begins execution. The test is executed before each iteration of the loop. If test is false, the loop terminates and program control passes to the statement immediately after the for loop. The increment is executed after each iteration of the loop and before the test. The increment typically updates the variables that control termination of the loop.

A typical for statement might look something like

for (int i = 0, int sum = 0; i < 10; i++) {

sum += i;

}

System.out.println("The sum of the integers from 0 to 9 is " + sum);

This is the general form for a while loop:

while (expr) {

// statement block

}

The loop iterates as long as expr is true.

This is a do loop:

do {

// statement block

} while (expr) ;

It is exactly the same as a while loop, but the loop will always iterate at least once, even if expr is false.

The switch statement can be used to compare a single expression to many different variables. Although the same thing can be accomplished with nested if statements, switch is shorter and more efficient:

switch(expr) {

case constant1:

// statement block

break;

case constant2:

// statement block

break;

...

default:

// statement block

break;

}

Here, expr is an expression. The value of expr is compared in sequence to the constants in each of the case clauses. If a match is found, the associated statement block is executed. The optional breakstatement causes program control to pass to the statement immediately after the switch block. If break is left out, the switch statement continues to evaluate the remaining statement blocks. (Incidentally breakcan also be used in loops, to exit the loop and resume execution at the next statement.) If the value of expr is not equal to any of the constants in the case clauses, the default statement block is executed.

Creating Classes and Objects

The next step in programming with Java is to define your own classes. A class definition may contain variables and methods. The variables are for storing data, and the methods are for accessing and working with that data.

Class definitions can also contain a special type of method called a constructor. A constructor is used to initialize a new instance of a class (meaning an object) when it is created. Constructors have the same name as the class. A class may have multiple constructors that take different arguments. For example, it might have one constructor that takes no arguments and initializes the variables in the object with default values, and a second constructor that takes a list of arguments and uses them to initialize the variables in the object.

The new operator creates an object. You cannot use an instance of an object until you have created it with new. It has the following syntax:

clsName obj = new clsName(args);

Here, clsName is the name of the class to be instantiated. A reference to the new object is assigned to the variable obj. new calls the constructor for the object with the arguments in args. Because Java has automatic garbage collection, you don’t need to tell it when you’re done using an object. Therefore, there is no equivalent for the “delete” operator from C++.

When you create an instance of an object, it comes with variables and methods that are defined in the class. The variables (called instance variables) are accessed like this:

obj.varName

Here, obj is a reference to an object and varName is the name of the instance variable.

The instance methods can be called like this:

obj.mthName (args)

Here, obj is a reference to an object and mthName is the name of the method. The optional arguments to the method are args.

This example shows how to define a class named StudentFile. This class has two variables, two constructors, and three methods:

public class StudentFile{

private String name; // This string holds the name of the student.

private int IDnum; // This integer is the ID number for the student.

public StudentFile() { // This is a constructor for StudentFile.

name=""; // It sets the variables to default values.

IDnum=0;

}

public StudentFile(String sName, int sIDnum) { // An alternate constructor.

this.SetStudentData (sName, sIDnum); // Call the method SetStudentData.

}

public void SetStudentData(String sName, int sIDnum) {

name=sName; // Save the student's name.

IDnum=sIDnum; // Save the ID number.

}

public String GetStudentName() // Returns the student's name.

return name;

}

public int GetStudentID() // This method returns the ID number.

return IDnum;

}

}

Notice that the keyword this refers to the current object, although it is often optional. The keyword public makes a variable or method visible to any part of your code. The keyword private makes a variable or method usable only within the class in which it is defined. The keyword protected is similar to private, except that subclasses can also use the variable or method.

In the preceding example, the private in front of the variable definitions provides encapsulation. This means that those variables are hidden from your other classes. You might think that you could save a lot of space by defining the class StudentFile as

class StudentFile{

public String name;

public int IDnum;

}

so that your other classes can use the variables directly In a short example like this, that might not be so bad. But the benefit of encapsulation is that other classes don’t need to understand the inner workings of your class. Even if you completely change how you represent data internally, other classes can still use the same methods for working with your class.

This example shows how you could instantiate and use objects of the class StudentFile just defined:

class StudentDemo {

public static void main (String args []) {

StudentFile FirstStudent = new StudentFile("Robin", 221486);

StudentFile SecondStudent = new StudentFile();

SecondStudent.SetStudentData("Ben", FirstStudent.GetStudentID 0+1) ;

}

}

The StudentDemo class defines the main() method for this application. The first and second lines in this method instantiate two StudentFile objects with the new operator. Variables FirstStudent and SecondStudent hold references to these objects.

Class Inheritance

Inheritance is a key advantage of object-oriented programming. It enables a class to reuse the state and behavior that is defined by a parent class. The parent class is called a superclass, and the child class is called a subclass. Unlike C++, Java does not support multiple inheritance. Each class can have only one superclass.

A subclass can be declared with the following syntax:

class clsName2 extends clsName1 {

// body of clsName2

}

Here, clsName2 is a subclass of clsName1. The subclass clsName2 will inherit all of the nonprivate variables and methods from clsName1. You can then use any of these variables and methods for clsName2just as you would if they were defined in the class itself.

If a class declaration does not include an extends clause, the Java compiler assumes that java.lang.Object is the superclass.

The following application illustrates a class inheritance hierarchy Class A extends Object. Class B extends A. Class C extends B. Each of these classes defines one instance variable.

The main() method of InheritanceDemo instantiates C. That new object has one copy of each instance variable defined by each of its superclasses. Those variables are initialized and displayed.

class Animal{

int age;

}

class Dog extends Animal {

String name;

void PrintInfo () {

System.out.println(name + "is " + age + "years old.");

}

}

class Papillon extends Dog {

boolean pet;

}

class InheritanceDemo {

public static void main (String args []) {

Papillon puppy = new Papillon() ;

puppy.age = 2;

puppy.name = "Kili";

puppy.pet = true;

puppy.PrintInfo();

}

}

The output from this application would look like:

Kili is 2 years old.

Method Overriding

Method overriding occurs when a subclass declares a method with the same method name and argument list as a method declared in one of its superclasses. When the method gets called, the new method is executed instead of the superclass method.

Java provides a mechanism that allows a subclass method to explicitly invoke an overridden superclass method. This is done by using the super keyword with the following syntax:

super.mthName (args);

Here, mthName is the name of the overridden method and args is the optional list of arguments.

The following application illustrates this concept. Class X extends Object. Class Y extends X. Class Z extends Y. Each of these classes defines and initializes one instance variable. Observe that class Yoverrides the display() method defined by its superclass (X) but also calls that method in X. Similarly, class Z overrides the display() method defined by its superclass (Y) but also calls that method in Y.

The main() method of OverridingDemo instantiates Z and invokes its display() method:

class X {

int x = 1;

void display() {

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

}

}

class Y extends X {

int y = 2;

void display() {

super.display();

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

}

}

class Z extends Y {

int z = 3;

void display() {

super.display();

System.out.println("z = " + z)

}

}

class OverridingDemo {

public static void main (String args [] {

Z obj = new Z();

obj . display() ;

}

}

Output from this application is shown here:

X = 1;

y = 2;

z = 3;

Static Methods and Variables

A class variable is associated with a class, rather than an object. Class variables are defined with the keyword static. This is often used with the keyword final to define constants that will be used by any object of a given class.

A class variable is accessed in this way:

clsName.varName

Here, clsName is the name of the class and varName is the name of the class variable. Note that we do not need to instantiate the class as an object in order to use varName.

You can also use static when declaring a method to create a class method. For example, Java includes a class called Math, which defines a class method named max(). Because it is a class method, you do not need to create a Math object in order to use max():

class StaticMethodDemo{

public static void main (String args []) {

System.out.println(Math.max(9, 3));

}

}

Interfaces

An interface is a group of constants and method declarations. It cannot define any implementations for those methods. In effect, an interface defines what must be done but not how it is done. A class can be declared to implement one or more interfaces.

The following application illustrates these concepts. The AntiTheftDevice interface declares two methods, and the Navigation interface declares one method. Class Automobile has subclasses named Model1 and Model2. The former implements both interfaces. The latter implements only the Navigation interface.

The main() method of the InterfaceDemo class creates Model1 and Model2 objects and invokes their methods:

interface AntiTheftDevice {

void lock();

void unlock() ;

}

interface Navigation {

void locate () ;

}

class Automobile {

}

class Model1 extends Automobile implements AntiTheftDevice, Navigation {

public void lock() {

System.out.println("Model1: lock");

}

public void unlock() {

System.out.println("Model1: unlock");

}

public void locate () {

System.out.println("Model1: locate");

}

}

class Model2 extends Automobile implements Navigation

public void locate () {

System.out.println("Model2: locate");

}

}

class InterfaceDemo {

public static void main (String args []) {

Model1 auto1 = new Model1() ;

auto1.lock();

auto1.unlock();

auto1.locate();

Navigation auto2 = new Model2();

auto2.locate ();

}

}

Interfaces can inherit from other interfaces with the extends keyword. Unlike classes, which can have only one superclass, a single interface can extend multiple interfaces.

Packages

A package is a group of classes and interfaces that are bundled together. Many packages are included by default in the Java API libraries, which come with the JDK. Table 25–3 summarizes some of these packages. Consult the official documentation at http://java.sun.eom/j2se/l.5.0/docs/api/index.html for a complete list of packages and classes.

Table 25–3: Java Packages

Package

Description

java.applet

Allows you to build applets

java.awt

Enables you to build graphical user interfaces

java.io

Supports input and output

java.lang

Provides core functionality

java.net

Enables networking

java.util

Offers utility functionality

javax.swing

Build customizable GUI controls

You can use the classes and interfaces in a package by specifying their fully qualified name (e.g., java.awt.Graphics.drawString). However, this can become tedious. To use an abbreviated name (such as drawString), add the import statement at the top of your file. It has either of the following two forms:

import java.awt.Graphics;

import java.awt.*;

The first form enables you to use an abbreviated name for an class or interface. It also allows you to document exactly which classes your code depends on. The second form allows you to use abbreviated names for all of the types in a given package.

The java.lang package is automatically imported into every source file. This provides convenient access to its classes and interfaces. These classes include Math, which has methods like sqrt, log, and cos, and String, which is discussed in the next section.

Strings

One of the most commonly used classes in java.lang is String. All string literals such as “Hello, world” are implemented as instances of this class. Java will automatically convert basic types to strings when necessary Java also supports the+operator, which concatenates two strings together.

The following sample application demonstrates some basic string commands:

class StringSample {

public static void main (String args []) {

String s = "String Sample";

System.out.println("The first character is: " + s.charAt(0));

System.out.println(s.substring(7) + s.substring (0, 6));

s = s.replace(" ", "_");

System.out.println(s.toUpperCase());

}

}

The output would look like this:

The first character is: S

SampleString

STRING__SAMPLE

As you can see, the charAt method returns the character at the given index. The substring method returns part of a string. The first argument is the character index where the substring begins, and the option second argument is the length of the substring. The replace method replaces all occurrences of the first argument with the second argument, and the method called toUpperCase converts a string to uppercase.

Vectors

The package java.util defines a number of useful classes, one of which is Vector. Vectors are similar to arrays; they store a set of objects of a given type and allow you to access each element by index. Unlike arrays, vectors automatically grow or shrink in size as you add or remove elements. When you create a vector, you can give it a hint about how much space to allocate so that it can be more efficient about memory storage.

The method add() appends a new element at the end of a vector by default, or you can explicitly specify an index at which to insert the element. The elementAt() method returns the value of an element at a given index. You can find the index for a value with the indexOf() method. You can remove() elements either by index or by value.

This example demonstrates some of these methods:

import java.util.Vector;

class VectorSample{

public static void main (String args []) {

// Create a new vector with an initial size of 10.

Vector<String> v=new Vector<String>(10);

v.add( "Element0");

v.add( "Element2") ;

v.add(1, "Element1"); // Inserts between the two above

System.out.println(v.indexOf ("Element2"));

for (byte c=0;c<v.size();c++) {

System.out.println(v.elementAt (c));

}

}

}

The output would look like this:

2

Element0

Element1

Element2

Vectors are commonly used in Java programming. However, vector operations are synchronized for use in multithreaded applications, which tends to make them slow. Many performance-minded Java coders prefer to use java.util.ArrayList, which has an interface similar to java.util.Vector but requires manual synchronization.

Exceptions

An exception is an object that is generated when a program encounters a problem during execution. Some examples of the conditions that cause an exception include integer division by zero, a negative array index, an out-of-bounds array index, and an incorrect number format. Exceptions are used more heavily in Java than many other programming languages.

Java allows you to handle exceptions according to the following syntax:

try {

// try block

}

catch(ExceptionType1 param1) {

// exception-handling block

}

...

catch (ExceptionType2 param2) {

// exception-handling block

}

finally {

// finally block

}

The try statement contains a block of statements. If a problem occurs during the execution of this code, an exception is thrown.

A sequence of catch blocks follows the try block. An argument is passed to each of these blocks. That argument is the exception object describing the problem.

If an exception is thrown during the execution of a try block, the JVM immediately stops execution of the try block and searches for a catch block to handle that type of exception. The search begins at the first catch clause. If the type of the exception object matches the type of the catch clause parameter, that block is executed. Otherwise, the following catch clauses are examined in sequence.

The finally block is optional. It’s always executed after completion of the try block or a catch block. (Even if you return from the method that contains the block.) In many cases, a finally block provides a useful way to relinquish resources. Each try block must have at least one catch or finally block. Otherwise, a compile error occurs.

Only one of the catch blocks will execute. If there is no type match between the exception object and the catch clause parameters, the finally block executes and the search continues in any enclosing tryblocks. If a match is not found in the current method, the search continues in the calling method. The search continues up the call stack in this manner. If no match is found, the exception is displayed by the default exception handler and the program is terminated.

The following application illustrates exception handling. The main() method includes a try block that attempts an integer division by zero. This generates an exception. Control passes to the first catch block, which displays the exception. When the catch block completes, the finally block executes:

import java.io.IOException;

class DivideByZero{

public static void main (String args []) {

try {

System.out.println("Before division");

System.out.println(1/0);

System.out.println("After division");

}

catch (IOException e) {

System.out.println(e);

}

catch(Exception e) {

System.out.println(e);

}

finally{

System.out.println("finally")

}

}

}

Output from this application is shown here:

Before division

java.lang.ArithmeticException: / by zero

finally

You can generate exceptions with throw. This can allow you to handle errors encountered during execution. Here’s an example of a method that throws an exception:

double PythagoreanTheorem (double a, double b) throws Exception {

if (a <= 0 | b <= 0) {

throw new Exception("not a valid triangle");

} else {

return Math.sqrt(a*a + b*b);

}

}

If you use this method, you will have to enclose it in a try/catch block, or the Java compiler will generate an error.

The java.lang package defines an Exception class. Its subclasses describe various types of problems that can occur during execution of a program. For example, an IOException is thrown by many of the methods in the java.io package to indicate problems during I/O activities. You can also create your own custom exceptions to describe application-specific problems by defining a subclass of Exception.

A Simple Java Applet

This section describes how to create, compile, and execute a Java applet that you can run in a web browser.

Create the HTML Source File

Use a text editor to create a file named Hello.html with the text

<applet code="HelloApplet" width=300 height=200>

</applet>

You could also embed this HTML tag in an existing web page.

Create and Compile the Java Source File

Now create a file named HelloApplet.java with the following contents:

import java.applet.Applet;

import java.awt.Graphics;

public class HelloApplet extends Applet{

public void paint (Graphics g) {

g.drawString ("Hello", 100, 100) ;

}

}

Consider each of the lines in this program. The first and second lines import the Applet class from the java.applet package and the Graphics class from the java.awt package. This allows you to use partially qualified names for these two classes.

The third line declares HelloApplet as a subclass of Applet. HelloApplet inherits all of the basic applet functionality from its superclass.

The fourth line overrides the paint() method. It receives a Graphics object as its argument. That object provides methods to draw on the screen.

The fifth line invokes the drawString() method of the Graphics object. The first argument to this method is a string to be output. The second and third arguments are the x and y positions at which the string should be located. The upper-left corner of the applet display area is position 0, 0. Values along the x axis increase toward the right. Values along the y axis increase toward the bottom. The total drawing area of the applet was configured in the Hello.html file.

Before you can run your applet, you must compile it using javac:

javac HelloApplet.java

Invoke the Applet Viewer

The applet viewer is one of the utilities that is included in the JDK. It allows you to execute an applet. Invoke this tool by entering the following on the command line:

appletviewer Hello.html

The applet appears as shown in Figure 25–1.

Image from book
Figure 25–1: A simple Java applet

It is also possible to run the appletviewer directly on a .java file (without an .html file) if you include the <applet> tags in a Java comment near the beginning of the file. However, you still need to compile your .java file with javac before running.

A more common way to view applets is in a web browser, by opening your .html file (to do this, look in the File menu for the option Open File). If it includes a JVM that is up to date, the browser will display the applet along with any HTML content.

The Abstract Window Toolkit (AWT)

The Abstract Window Toolkit (AWT) is a large package that enables you to build graphical user interfaces. Some of the components that can be used are buttons, check boxes, choices, labels, lists, scrollbars, text areas, and text fields. Dialog boxes can be created to prompt a user for information. Layout managers are available to arrange the elements in a window.

A complete discussion of the AWT components is beyond the scope of this book. However, the following simple applet demonstrates how to create a user interface that displays three buttons:

import java.applet.*;

import java.awt.*;

/*

<applet code="ButtonApplet" width=400 height=60>

</applet>

*/

public class ButtonApplet extends Applet {

public void init(){

Button b1 = new Button("Yes");

add(b1);

Button b2 = new Button("No");

add (b2);

Button b3 = new Button("Undecided");

add (b3);

}

}

You can run this applet with appletviewer ButtonApplet.java. The output will appear as shown in Figure 25–2.

Image from book
Figure 25–2: A simple use of AWT components

In the second edition of Java, a package called javax.swing was added to the platform. This package, referred to as Swing, is an advanced graphical user interface built on top of the AWT. Swing provides a more customizable look and feel for Java programs. If you plan to create extensive graphical user interfaces in Java, you should consider further investigation into Swing. The section “How to Find Out More” at the end of this chapter includes sources for learning about Swing.

Event Handling

Events are generated when a user interacts with the AWT components in a graphical user interface. For example, an event is generated when a button is pressed, the mouse is clicked, a scrollbar is manipulated, a menu item is selected, or a key is pressed.

A source generates an event and sends it to one or more listeners. This is known as the delegation event model. The source delegates the handling of that event to the listeners.

A source must implement methods that allow listeners to register and unregister for events. A listener must implement methods from a specific interface in order to receive notifications about this type of event. The java.awt.event package defines classes for the different types of AWT events. It also declares listener interfaces for these events.

For example, a button generates a java.awt.event.ActionEvent object each time it is pressed. Listeners implement the java.awt.event.ActionListener interface to receive these notifications. This interface declares one method whose signature is shown here:

void actionPerformed(ActionEvent ae)

Here, ae is the ActionEvent object that was generated by the button.

Listeners register and unregister for this type of event notification via the following methods:

void addActionListener(ActionListener al)

void removeActionListener(ActionListener al)

Here, al is the object that implements the ActionListener interface.

The following example illustrates event handling:

import java.applet.*;

import java.awt.*;

import java.awt.event.*;

/*

<applet code="ButtonEventsApplet" width=400 height=60>

</applet>

*/

public class ButtonEventsApplet extends Applet

implements ActionListener {

Label label;

public void init() {

Button b1 = new Button("Yes");

b1.addActionListener(this);

add(b1);

Button b2 = new Button("No");

b2.addActionListener(this);

add (b2);

Button b3 = new Button("Undecided");

b3.addActionListener(this);

add (b3);

label = new Label(" ");

add(label);

}

public void actionPerformed(ActionEvent ae){

label.setText(ae.getActionCommand());

}

}

The ButtonEventsApplet class implements ActionListener. The init() method creates three buttons and adds these to the applet. In addition, the applet itself is registered to receive action events generated by each of these buttons. A label is also added to the applet. This is used to display a string each time a button is pressed.

The actionPerformed() method is invoked when a button is pressed. The getActionCommand() method returns the command string associated with this action event. That string is the label on the button. The setText() method is invoked to display this string in the label.

Multithreaded Programming

Up until now, your Java programs have only executed a single sequence of instructions. A program can run multiple sequences of instructions in parallel by using multiple threads. The JVM manages these threads and executes all of them.

The Thread class in the java.lang package allows you to create and manage threads. You define a thread by extending Thread:

class ThreadX extends Thread {

public void run() {

..// logic for the thread

}

}

Here, ThreadX extends Thread. The run() method defines the behavior of the thread.

An instance of the thread can be created and started as shown here:

ThreadX tx = new ThreadX();

tx.start ();

Here, the first line creates an instance of ThreadX. The second line invokes the start() method of the Thread class, which begins execution of the thread. The start() method causes the run() method of ThreadXto be executed.

The following example demonstrates how to create an application that contains a thread. The thread displays an updated counter value every second:

class ThreadX extends Thread{

public void run() {

try {

int counter = 0;

while (true) {

Thread.sleep(1000);

System.out.println(counter++);

}

}

catch(InterruptedException ex) {

ex.printStackTrace();

}

}

}

class ThreadDemo {

public static void main (String args [] {

ThreadX tx = new ThreadX();

tx.start ();

}

}

Output from this thread during its first three seconds is shown here:

0

1

2

You can use threads in both applets and applications. You might, for example, create an applet that implements an animation by using a thread.

The Java language includes mechanisms to coordinate the activities of several threads in a process. Data shared by more than one thread can be corrupted unless those threads are properly synchronized. Consult the Sun documentation for more details.

Summary

This chapter introduced the Java language and the tools you need for working with Java. It described the key components of the language and some of its additional capabilities, such as GUI programming and multithreaded applications.

Many additional capabilities of the Java language and class libraries have not been discussed in this chapter. For example,

§ Java EE is the enterprise version of Java, for creating server-side applications.

§ Java ME is a version of Java for creating applications for devices such as cell phones.

§ Servlets are Java objects that dynamically extend the functionality of a Web server. Applets and servlets work together to build a Web application.

§ JavaBeans are software components written in Java. The Enterprise JavaBeans specification defines a set of services that are available for Java components that execute on a server.

§ Remote Method Invocation (RMI) enables Java objects on one machine to invoke methods of Java objects on another machine.

§ Java Card provides a specialized JVM that executes on a smart card.

Consult the Sun Microsystems web site at http://java.sun.com to learn more about these and other Java-related technologies.

Note that JavaScript, which is a scripting language that is often used to embed code in web pages, is not on this list. That’s because it is not especially similar to Java, except for the name. JavaScript is discussed in Chapter 27, along with other Internet programming languages.

How to Find Out More

These are two of the best references available for Java programmers. They are targeted at someone who is already somewhat comfortable with Java, or has a strong understanding of C++:

· Block, Joshua. Effective Java Programming Language Guide. 1st ed. Boston, MA: Addison Wesley, 2001.

· Haggar, Peter. Practical Java Programming Language Guide. 1st ed. Boston, MA: Addison Wesley, 2000.

A very accessible beginner’s guide to Java is

· Sierra, Kathy, and Bert Bates. Head First Java. 2nd ed. Sebastopol, CA: O’Reilly, 2005.

A good introduction to Swing and Java GUIs is

· Walrath, Kathy et al. The JFC Swing Tutorial: A Guide to Constructing GUIs. 2nd ed. Boston, MA: Addison Wesley, 2004.

If you plan to use J2EE for enterprise development, check out

· Johnson, Rod, and Juergen Hoeller. Expert One-on-One J2EE Development without EJB. 1st ed. Indianapolis, IN: Wrox-Wiley, 2004.

Sun has extensive Java documentation on the web, including tutorials and a complete API reference, at

· http://java.sun.com/docs/