BUY THIS BOOK
Add to Cart

Print Book $44.95


Add to Cart

Print+PDF $58.44

Add to Cart

PDF $35.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £31.95

What is this?

Looking to Reprint or License this content?


Java in a Nutshell
Java in a Nutshell, Fifth Edition

By David Flanagan
Book Price: $44.95 USD
£31.95 GBP
PDF Price: $35.99

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introduction
Welcome to Java. This chapter begins by explaining what Java is and describing some of the features that distinguish it from other programming languages. Next, it outlines the structure of this book, with special emphasis on what is new in Java 5.0. Finally, as a quick tutorial introduction to the language, it walks you through a simple Java program you can type, compile, and run.
In discussing Java, it is important to distinguish between the Java programming language, the Java Virtual Machine, and the Java platform. The Java programming language is the language in which Java applications, applets, servlets, and components are written. When a Java program is compiled, it is converted to byte codes that are the portable machine language of a CPU architecture known as the Java Virtual Machine (also called the Java VM or JVM). The JVM can be implemented directly in hardware, but it is usually implemented in the form of a software program that interprets and executes byte codes.
The Java platform is distinct from both the Java language and Java VM. The Java platform is the predefined set of Java classes that exist on every Java installation; these classes are available for use by all Java programs. The Java platform is also sometimes referred to as the Java runtime environment or the core Java APIs (application programming interfaces). The Java platform can be extended with optional packages (formerly called standard extensions). These APIs exist in some Java installations but are not guaranteed to exist in all installations.
The Java programming language is a state-of-the-art, object-oriented language that has a syntax similar to that of C. The language designers strove to make the Java language powerful, but, at the same time, they tried to avoid the overly complex features that have bogged down other object-oriented languages like C++. By keeping the language simple, the designers also made it easier for programmers to write robust, bug-free code. As a result of its elegant design and next-generation features, the Java language has proved popular with programmers, who typically find it a pleasure to work with Java after struggling with more difficult, less powerful languages.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Is Java?
In discussing Java, it is important to distinguish between the Java programming language, the Java Virtual Machine, and the Java platform. The Java programming language is the language in which Java applications, applets, servlets, and components are written. When a Java program is compiled, it is converted to byte codes that are the portable machine language of a CPU architecture known as the Java Virtual Machine (also called the Java VM or JVM). The JVM can be implemented directly in hardware, but it is usually implemented in the form of a software program that interprets and executes byte codes.
The Java platform is distinct from both the Java language and Java VM. The Java platform is the predefined set of Java classes that exist on every Java installation; these classes are available for use by all Java programs. The Java platform is also sometimes referred to as the Java runtime environment or the core Java APIs (application programming interfaces). The Java platform can be extended with optional packages (formerly called standard extensions). These APIs exist in some Java installations but are not guaranteed to exist in all installations.
The Java programming language is a state-of-the-art, object-oriented language that has a syntax similar to that of C. The language designers strove to make the Java language powerful, but, at the same time, they tried to avoid the overly complex features that have bogged down other object-oriented languages like C++. By keeping the language simple, the designers also made it easier for programmers to write robust, bug-free code. As a result of its elegant design and next-generation features, the Java language has proved popular with programmers, who typically find it a pleasure to work with Java after struggling with more difficult, less powerful languages.
Java 5.0, the latest version of the Java language, includes a number of new language features, most notably generic types, which increase both the complexity and the power of the language. Most experienced Java programmers have welcomed the new features, despite the added complexity they bring.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Key Benefits of Java
Why use Java at all? Is it worth learning a new language and a new platform? This section explores some of the key benefits of Java.
Sun identifies "Write once, run anywhere" as the core value proposition of the Java platform. Translated from business jargon, this means that the most important promise of Java technology is that you have to write your application only once—for the Java platform—and then you'll be able to run it anywhere.
Anywhere, that is, that supports the Java platform. Fortunately, Java support is becoming ubiquitous. It is integrated into practically all major operating systems. It is built into the popular web browsers, which places it on virtually every Internet-connected PC in the world. It is even being built into consumer electronic devices such as television set-top boxes, PDAs, and cell phones.
Another key benefit of Java is its security features. Both the language and the platform were designed from the ground up with security in mind. The Java platform allows users to download untrusted code over a network and run it in a secure environment in which it cannot do any harm: untrusted code cannot infect the host system with a virus, cannot read or write files from the hard drive, and so forth. This capability alone makes the Java platform unique.
Java 1.2 took the security model a step further. It made security levels and restrictions highly configurable and extended them beyond applets. As of Java 1.2, any Java code, whether it is an applet, a servlet, a JavaBeans component, or a complete Java application, can be run with restricted permissions that prevent it from doing harm to the host system.
The security features of the Java language and platform have been subjected to intense scrutiny by security experts around the world. In the earlier days of Java, security-related bugs, some of them potentially serious, were found and promptly fixed. Because of the strong security promises Java makes, it is big news when a new security bug is found. No other mainstream platform can make security guarantees nearly as strong as those Java makes. No one can say that Java security holes will not be found in the future, but if Java's security is not yet perfect, it has been proven strong enough for practical day-to-day use and is certainly better than any of the alternatives.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
An Example Program
Example 1-1 shows a Java program to compute factorials. Note that the numbers at the beginning of each line are not part of the program; they are there for ease of reference when we dissect the program line-by-line.
Example 1-1. Factorial.java: a program to compute factorials
 1 /**
 2  * This program computes the factorial of a number
 3  */
 4 public class Factorial {                   // Define a class
 5   public static void main(String[] args) { // The program starts here
 6     int input = Integer.parseInt(args[0]); // Get the user's input
 7     double result = factorial(input);      // Compute the factorial
 8     System.out.println(result);            // Print out the result
 9   }                                        // The main() method ends here
10 
11   public static double factorial(int x) {  // This method computes x!
12     if (x < 0)                             // Check for bad input
13       return 0.0;                          // If bad, return 0
14     double fact = 1.0;                     // Begin with an initial value
15     while(x > 1) {                         // Loop until x equals 1
16       fact = fact * x;                     // Multiply by x each time
17       x = x - 1;                           // And then decrement x
18     }                                      // Jump back to start of loop
19     return fact;                           // Return the result
20   }                                        // factorial() ends here
21 }                                          // The class ends here
Before we look at how the program works, we must first discuss how to run it. In order to compile and run the program, you need a Java development kit (JDK) of some sort. Sun Microsystems created the Java language and ships a free JDK for its Solaris operating system and also for Linux and Microsoft Windows platforms. At the time of this writing, the current version of Sun's JDK is available for download from
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Java Syntax from the Ground Up
This chapter is a terse but comprehensive introduction to Java syntax. It is written primarily for readers who are new to the language but have at least some previous programming experience. Determined novices with no prior programming experience may also find it useful. If you already know Java, you should find it a useful language reference. The chapter includes comparisons of Java to C and C++ for the benefit of programmers coming from those languages.
This chapter documents the syntax of Java programs by starting at the very lowest level of Java syntax and building from there, covering increasingly higher orders of structure. It covers:
  • The characters used to write Java programs and the encoding of those characters.
  • Literal values, identifiers, and other tokens that comprise a Java program.
  • The data types that Java can manipulate.
  • The operators used in Java to group individual tokens into larger expressions.
  • Statements, which group expressions and other statements to form logical chunks of Java code.
  • Methods (also called functions, procedures, or subroutines), which are named collections of Java statements that can be invoked by other Java code.
  • Classes, which are collections of methods and fields. Classes are the central program element in Java and form the basis for object-oriented programming. Chapter 3 is devoted entirely to a discussion of classes and objects.
  • Packages, which are collections of related classes.
  • Java programs, which consist of one or more interacting classes that may be drawn from one or more packages.
The syntax of most programming languages is complex, and Java is no exception. In general, it is not possible to document all elements of a language without referring to other elements that have not yet been discussed. For example, it is not really possible to explain in a meaningful way the operators and statements supported by Java without referring to objects. But it is also not possible to document objects thoroughly without referring to the operators and statements of the language. The process of learning Java, or any language, is therefore an iterative one. If you are new to Java (or a Java-style programming language), you may find that you benefit greatly from working through this chapter and the next
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java Programs from the Top Down
Before we begin our bottom-up exploration of Java syntax, let's take a moment for a top-down overview of a Java program. Java programs consist of one or more files, or compilation units , of Java source code. Near the end of the chapter, we describe the structure of a Java file and explain how to compile and run a Java program. Each compilation unit begins with an optional package declaration followed by zero or more import declarations. These declarations specify the namespace within which the compilation unit will define names, and the namespaces from which the compilation unit imports names. We'll see package and import again in Section 2.10 later in this chapter.
The optional package and import declarations are followed by zero or more reference type definitions. These are typically class or interface definitions, but in Java 5.0 and later, they can also be enum definitions or annotation definitions. The general features of reference types are covered later in this chapter, and detailed coverage of the various kinds of reference types is in Chapters Chapter 3 and Chapter 4.
Type definitions include members such as fields, methods, and constructors. Methods are the most important type member. Methods are blocks of Java code comprised of statements . Most statements include expressions , which are built using operators and values known as primitive data types . Finally, the keywords used to write statements, the punctuation characters that represent operators, and the literals values that appear in a program are all tokens , which are described next. As the name of this section implies, this chapter moves from describing the smallest units, tokens, to progressively larger units. Since the concepts build upon one another, we recommend reading this chapter sequentially.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Lexical Structure
This section explains the lexical structure of a Java program. It starts with a discussion of the Unicode character set in which Java programs are written . It then covers the tokens that comprise a Java program, explaining comments, identifiers, reserved words, literals, and so on.
Java programs are written using Unicode. You can use Unicode characters anywhere in a Java program, including comments and identifiers such as variable names. Unlike the 7-bit ASCII character set, which is useful only for English, and the 8-bit ISO Latin-1 character set, which is useful only for major Western European languages, the Unicode character set can represent virtually every written language in common use on the planet. 16-bit Unicode characters are typically written to files using an encoding known as UTF-8, which converts the 16-bit characters into a stream of bytes. The format is designed so that plain ASCII text (and the 7-bit characters of Latin-1) are valid UTF-8 byte streams. Thus, you can simply write plain ASCII programs, and they will work as valid Unicode.
If you do not use a Unicode-enabled text editor, or if you do not want to force other programmers who view or edit your code to use a Unicode-enabled editor, you can embed Unicode characters into your Java programs using the special Unicode escape sequence \u xxxx, in other words, a backslash and a lowercase u, followed by four hexadecimal characters. For example, \u0020 is the space character, and \u03c0 is the character .
Unicode 3.1 and above, used in Java 5.0 and later, includes "supplementary characters" that require 21 bits to represent. 16-bit encodings of Unicode characters represent these supplementary characters using a surrogate pair , which is a sequence of two 16-bit characters taken from a special reserved range of the 16-bit encoding space. If you ever need to include one of these (rarely used) supplementary characters in Java source code, use two
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Primitive Data Types
Java supports eight basic data types known as primitive types as secribed in Table 2-1. The primitive types include a boolean type, a character type, four integer types, and two floating-point types. The four integer types and the two floating-point types differ in the number of bits that represent them and therefore in the range of numbers they can represent. The next section summarizes these primitive data types. In addition to these primitive types, Java supports nonprimitive data types such as classes, interfaces, and arrays. These composite types are known as reference types, which are introduced in Section 2.9 later in this chapter.
Table 2-1: Java primitive data types
Type
Contains
Default
Size
Range
boolean
true or false
false
1 bit
NA
char
Unicode character
\u0000
16 bits
\u0000 to \uFFFF
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Expressions and Operators
So far in this chapter, we've learned about the primitive types that Java programs can manipulate and seen how to include primitive values as literals in a Java program. We've also used variables as symbolic names that represent, or hold, values. These literals and variables are the tokens out of which Java programs are built.
An expression is the next higher level of structure in a Java program. The Java interpreter evaluates an expression to compute its value. The very simplest expressions are called primary expressions and consist of literals and variables. So, for example, the following are all expressions:
1.7         // A floating-point literal
true        // A boolean literal
sum         // A variable
When the Java interpreter evaluates a literal expression, the resulting value is the literal itself. When the interpreter evaluates a variable expression, the resulting value is the value stored in the variable.
Primary expressions are not very interesting. More complex expressions are made by using operators to combine primary expressions. For example, the following expression uses the assignment operator to combine two primary expressions—a variable and a floating-point literal—into an assignment expression:
sum = 1.7
But operators are used not only with primary expressions; they can also be used with expressions at any level of complexity. The following are all legal expressions:
sum = 1 + 2 + 3*1.2 + (4 + 8)/3.0
sum/Math.sqrt(3.0 * 1.234)
(int)(sum + 33)
The kinds of expressions you can write in a programming language depend entirely on the set of operators available to you. Table 2-4 summarizes the operators available in Java. The P and A columns of the table specify the precedence and associativity of each group of related operators, respectively. These concepts—and the operators themselves—are explained in more detail in the following sections.
Table 2-4:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Statements
A statement is a single command executed by the Java interpreter. By default, the Java interpreter runs one statement after another, in the order they are written. Many of the statements defined by Java, however, are flow-control statements, such as conditionals and loops, that alter this default order of execution in well-defined ways. Table 2-5 summarizes the statements defined by Java.
Table 2-5: Java statements
Statement
Purpose
Syntax
expression
side effects
var = expr ; expr ++; method ( ); new Type ( );
compound
group statements
{ statements }
empty
do nothing
;
labeled
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Methods
A method is a named sequence of Java statements that can be invoked by other Java code. When a method is invoked, it is passed zero or more values known as arguments . The method performs some computations and, optionally, returns a value. As described in Section 2.4 earlier in this chapter, a method invocation is an expression that is evaluated by the Java interpreter. Because method invocations can have side effects, however, they can also be used as expression statements. This section does not discuss method invocation, but instead describes how to define methods.
You already know how to define the body of a method; it is simply an arbitrary sequence of statements enclosed within curly braces. What is more interesting about a method is its signature . The signature specifies the following:
  • The name of the method
  • The number, order, type, and name of the parameters used by the method
  • The type of the value returned by the method
  • The checked exceptions that the method can throw (the signature may also list unchecked exceptions, but these are not required)
  • Various method modifiers that provide additional information about the method
A method signature defines everything you need to know about a method before calling it. It is the method specification and defines the API for the method. The reference section of this book is essentially a list of method signatures for all publicly accessible methods of all publicly accessible classes of the Java platform. In order to use the reference section of this book, you need to know how to read a method signature. And, in order to write Java programs, you need to know how to define your own methods, each of which begins with a method signature.
A method signature looks like this:
                  modifiers 
                  type  
                  name ( paramlist ) [ throws exceptions ]
The signature (the method specification) is followed by the method body (the method implementation), which is simply a sequence of Java statements enclosed in curly braces. If the method is
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Classes and Objects Introduced
Now that we have introduced operators, expressions, statements, and methods, we can finally talk about classes. A class is a named collection of fields that hold data values and methods that operate on those values. Classes are just one of five reference types supported by Java, but they are the most important type. Classes are thoroughly documented in a chapter of their own, Chapter 3. We introduce them here, however, because they are the next higher level of syntax after methods, and because the rest of this chapter requires a basic familiarity with the concept of class and the basic syntax for defining a class, instantiating it, and using the resulting object.
The most important thing about classes is that they define new data types. For example, you might define a class named Point to represent a data point in the two-dimensional Cartesian coordinate system. This class would define fields (each of type double) to hold the X and Y coordinates of a point and methods to manipulate and operate on the point. The Point class is a new data type.
When discussing data types, it is important to distinguish between the data type itself and the values the data type represents. char is a data type: it represents Unicode characters. But a char value represents a single specific character. A class is a data type; a class value is called an object. We use the name class because each class defines a type (or kind, or species, or class) of objects. The Point class is a data type that represents X,Y points, while a Point object represents a single specific X,Y point. As you might imagine, classes and their objects are closely linked. In the sections that follow, we will discuss both.
Here is a possible definition of the Point class we have been discussing:
/** Represents a Cartesian (x,y) point */
public class Point {
     public double x, y;                    // The coordinates of the point
     public Point(double x, double y) {     // A constructor that
         this.x = x; this.y = y;            // initializes the fields
     }

     public double distanceFromOrigin(  ) {   // A method that operates on
         return Math.sqrt(x*x + y*y);       // the x and y fields
     }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Arrays
An array is a special kind of object that holds zero or more primitive values or references. These values are held in the elements of the array, which are unnamed variables referred to by their position or index. The type of an array is characterized by its element type , and all elements of the array must be of that type.
Array elements are numbered starting with zero, and valid indexes range from zero to the number of elements minus one. The array element with index 1, for example, is the second element in the array. The number of elements in an array is its length. The length of an array is specified when the array is created, and it never changes.
The element type of an array may be any valid Java type, including array types. This means that Java supports arrays of arrays, which provide a kind of multidimensional array capability. Java does not support the matrix-style multidimensional arrays found in some languages.
Array types are reference types, just as classes are. Instances of arrays are objects, just as the instances of a class are. Unlike classes, array types do not have to be defined. Simply place square brackets after the element type. For example, the following code declares three variables of array type:
byte b;                        // byte is a primitive type
byte[] arrayOfBytes;           // byte[] is an array type: array of byte
byte[][] arrayOfArrayOfBytes;  // byte[][] is another type: array of byte[]
String[] points;               // String[] is an array of String objects
The length of an array is not part of the array type. It is not possible, for example, to declare a method that expects an array of exactly four int values, for example. If a method parameter is of type int[ ], a caller can pass an array with any number (including zero) of elements.
Array types are not classes, but array instances are objects. This means that arrays inherit the methods of java.lang.Object. Arrays implement the Cloneable interface and override the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Reference Types
Now that we've covered arrays and introduced classes and objects, we can turn to a more general description of reference types. Classes and arrays are two of Java's five kinds of reference types. Classes were introduced earlier and are covered in complete detail, along with interfaces, in Chapter 3. Enumerated types and annotation types are reference types introduced in Java 5.0 (see Chapter 4).
This section does not cover specific syntax for any particular reference type, but instead explains the general behavior of reference types and illustrates how they differ from Java's primitive types. In this section, the term object refers to a value or instance of any reference type, including arrays.
Reference types and objects differ substantially from primitive types and their primitive values:
  • Eight primitive types are defined by the Java language. Reference types are user-defined, so there is an unlimited number of them. For example, a program might define a class named Point and use objects of this newly defined type to store and manipulate X,Y points in a Cartesian coordinate system. The same program might use an array of characters—of type char[ ]—to store text and might use an array of Point objects—of type Point[ ]—to store a sequence of points.
  • Primitive types represent single values. Reference types are aggregate types that hold zero or more primitive values or objects. Our hypothetical Point class, for example, might hold two double values to represent the X and Y coordinates of the points. The char[ ] and Point[ ] array types are obviously aggregate types because they hold a sequence of primitive char values or Point objects.
  • Primitive types require between one and eight bytes of memory. When a primitive value is stored in a variable or passed to a method, the computer makes a copy of the bytes that hold the value. Objects, on the other hand, may require substantially more memory. Memory to store an object is dynamically allocated on the heap when the object is created and this memory is automatically "garbage-collected" when the object is no longer needed. When an object is assigned to a variable or passed to a method, the memory that represents the object is not copied. Instead, only a reference to that memory is stored in the variable or passed to the method.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Packages and the Java Namespace
A package is a named collection of classes, interfaces, and other reference types. Packages serve to group related classes and define a namespace for the classes they contain.
The core classes of the Java platform are in packages whose names begin with java. For example, the most fundamental classes of the language are in the package java.lang. Various utility classes are in java.util. Classes for input and output are in java.io, and classes for networking are in java.net. Some of these packages contain subpackages, such as java.lang.reflect and java.util.regex. Extensions to the Java platform that have been standardized by Sun typically have package names that begin with javax. Some of these extensions, such as javax.swing and its myriad subpackages, were later adopted into the core platform itself. Finally, the Java platform also includes several "endorsed standards," which have packages named after the standards body that created them, such as org.w3c and org.omg.
Every class has both a simple name, which is the name given to it in its definition, and a fully qualified name, which includes the name of the package of which it is a part. The String class, for example, is part of the java.lang package, so its fully qualified name is java.lang.String.
This section explains how to place your own classes and interfaces into a package and how to choose a package name that won't conflict with anyone else's package name. Next, it explains how to selectively import type names into the namespace so that you don't have to type the package name of every class or interface you use. Finally, the section explains a feature that is new in Java 5.0: the ability to import static members of types into the namespace so that you don't need to prefix these with a package name or a class name.
To specify the package a class is to be part of, you use a package declaration. The package
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java File Structure
This chapter has taken us from the smallest to the largest elements of Java syntax, from individual characters and tokens to operators, expressions, statements, and methods, and on up to classes and packages. From a practical standpoint, the unit of Java program structure you will be dealing with most often is the Java file. A Java file is the smallest unit of Java code that can be compiled by the Java compiler. A Java file consists of:
  • An optional package directive
  • Zero or more import or import static directives
  • One or more type definitions
These elements can be interspersed with comments, of course, but they must appear in this order. This is all there is to a Java file. All Java statements (except the package and import directives, which are not true statements) must appear within methods, and all methods must appear within a type definition.
Java files have a couple of other important restrictions. First, each file can contain at most one class that is declared public. A public class is one that is designed for use by other classes in other packages. This restriction on public classes only applies to top-level classes; a class can contain any number of nested or inner classes that are declared public. We'll see more about the public modifier and nested classes in Chapter 3.
The second restriction concerns the filename of a Java file. If a Java file contains a public class, the name of the file must be the same as the name of the class, with the extension .java appended. Thus, if Point is defined as a public class, its source code must appear in a file named Point.java. Regardless of whether your classes are public or not, it is good programming practice to define only one per file and to give the file the same name as the class.
When a Java file is compiled, each of the classes it defines is compiled into a separate class file that contains Java byte codes to be interpreted by the Java Virtual Machine. A class file has the same name as the class it defines, with the extension
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Defining and Running Java Programs
A Java program consists of a set of interacting class definitions. But not every Java class or Java file defines a program. To create a program, you must define a class that has a special method with the following signature:
public static void main(String[] args)
This main( ) method is the main entry point for your program. It is where the Java interpreter starts running. This method is passed an array of strings and returns no value. When main( ) returns, the Java interpreter exits (unless main( ) has created separate threads, in which case the interpreter waits for all those threads to exit).
To run a Java program, you run the Java interpreter, java , specifying the fully qualified name of the class that contains the main( ) method. Note that you specify the name of the class, not the name of the class file that contains the class. Any additional arguments you specify on the command line are passed to the main( ) method as its String[ ] parameter. You may also need to specify the -classpath option (or -cp) to tell the interpreter where to look for the classes needed by the program. Consider the following command:
% java -classpath /usr/local/Jude com.davidflanagan.jude.Jude datafile.jude
            
java is the command to run the Java interpreter. -classpath /usr/local/Jude tells the interpreter where to look for .class files. com.davidflanagan.jude.Jude is the name of the program to run (i.e., the name of the class that defines the main( ) method). Finally, datafile.jude is a string that is passed to that main( ) method as the single element of an array of String objects.
There is an easier way to run programs. If a program and all its auxiliary classes (except those that are part of the Java platform) have been properly bundled in a Java archive (JAR) file, you can run the program simply by specifying the name of the JAR file:
% java -jar /usr/local/Jude/jude.jar datafile.jude
            
Some operating systems make JAR files automatically executable. On those systems, you can simply say:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Differences Between C and Java
If you are a C or C++ programmer, you should have found much of the syntax of Java—particularly at the level of operators and statements—to be familiar. Because Java and C are so similar in some ways, it is important for C and C++ programmers to understand where the similarities end. C and Java differ in important ways, as summarized in the following list:
No preprocessor
Java does not include a preprocessor and does not define any analogs of the #define, #include, and #ifdef directives. Constant definitions are replaced with static final fields in Java. (See the java.lang.Math.PI field for an example.) Macro definitions are not available in Java, but advanced compiler technology and inlining has made them less useful. Java does not require an #include directive because Java has no header files. Java class files contain both the class API and the class implementation, and the compiler reads API information from class files as necessary. Java lacks any form of conditional compilation, but its cross-platform portability means that this feature is rarely needed.
No global variables
Java defines a very clean namespace. Packages contain classes, classes contain fields and methods, and methods contain local variables. But Java has no global variables, and thus there is no possibility of namespace collisions among those variables.
Well-defined primitive type sizes
All the primitive types in Java have well-defined sizes. In C, the size of short, int, and long types is platform-dependent, which hampers portability.
No pointers
Java classes and arrays are reference types, and references to objects and arrays are akin to pointers in C. Unlike C pointers, however, references in Java are entirely opaque. There is no way to convert a reference to a primitive type, and a reference cannot be incremented or decremented. There is no address-of operator like &, dereference operator like * or ->, or sizeof operator. Pointers are a notorious source of bugs. Eliminating them simplifies the language and makes Java programs more robust and secure.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Object-Oriented Programming in Java
Now that we've covered fundamental Java syntax, we are ready to begin object-oriented programming in Java. All Java programs use objects, and the type of an object is defined by its class or interface. Every Java program is defined as a class, and nontrivial programs usually include a number of classes and interface definitions. This chapter explains how to define new classes and interfaces and how to do object-oriented programming with them.
This is a relatively long and detailed chapter, so we begin with an overview and some definitions. A class is a collection of fields that hold values and methods that operate on those values. Classes are the most fundamental structural element of all Java programs. You cannot write Java code without defining a class. All Java statements appear within methods, and all methods are implemented within classes.
A class defines a new reference type, such as the Point type defined in Chapter 2. An object is an instance of a class. The Point class defines a type that is the set of all possible two-dimensional points. A Point object is a value of that type: it represents a single two-dimensional point.
Objects are usually created by instantiating a class with the new keyword and a constructor invocation, as shown here:
Point p = new Point(1.0, 2.0);
Constructors are covered in Section 3.3 later in this chapter.
A class definition consists of a signature and a body . The class signature defines the name of the class and may also specify other important information. The body of a class is a set of members enclosed in curly braces. The members of a class may include fields and methods, constructors and initializers, and nested types.
Members can be static or nonstatic. A static member belongs to the class itself while a nonstatic member is associated with the instances of a class (see Section 3.2 later in this chapter).
The signature of a class may declare that the class
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Class Definition Syntax
At its simplest level, a class definition consists of the keyword class followed by the name of the class and a set of class members within curly braces. The class keyword may be preceded by modifier keywords and annotations (see Chapter 4). If the class extends another class, the class name is followed by the extends keyword and the name of the class being extended. If the class implements one or more interfaces then the class name or the extends clause is followed by the implements keyword and a comma-separated list of interface names. For example:
public class Integer extends Number implements Serializable, Comparable {
    // class members go here
}
Generic class declarations include additional syntax that is covered in Chapter 4.
Class declarations may include zero or more of the following modifiers:
public
A public class is visible to classes defined outside of its package. See Section 3.6 later in this chapter.
abstract
An abstract class is one whose implementation is incomplete and cannot be instantiated. Any class with one or more abstract methods must be declared abstract.
final
The final modifier specifies that the class may not be extended. Declaring a class final may enable the Java VM to optimize its methods.
strictfp
If a class is declared strictfp , all its methods behave as if they were declared strictfp. This rarely used modifier is discussed in Section 2.6 in Chapter 2.
A class cannot be both abstract and final. By convention, if a class has more than one modifier, they appear in the order shown.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Fields and Methods
A class can be viewed as a collection of data and code to operate on that data. The data is stored in fields, and the code is organized into methods. This section covers fields and methods, the two most important kinds of class members. Fields and methods come in two distinct types: class members (also known as static members) are associated with the class itself, while instance members are associated with individual instances of the class (i.e., with objects). This gives us four kinds of members:
  • Class fields
  • Class methods
  • Instance fields
  • Instance methods
The simple class definition for the class Circle, shown in Example 3-1, contains all four types of members.
Example 3-1. A simple class and its members
public class Circle {
  // A class field
  public static final double PI= 3.14159;     // A useful constant

  // A class method: just compute a value based on the arguments
  public static double radiansToDegrees(double rads) { 
    return rads * 180 / PI; 
  }

  // An instance field
  public double r;                  // The radius of the circle

  // Two instance methods: they operate on the instance fields of an object
  public double area() {            // Compute the area of the circle
    return PI * r * r; 
  }
  public double circumference() {   // Compute the circumference of the circle
    return 2 * PI * r; 
  }
}
The following sections explain all four kinds of members. First, however, we cover field declaration syntax. (Method declaration syntax is covered in Section 2.6 later in this chapter.)
Field declaration syntax is much like the syntax for declaring local variables (see Chapter 2) except that field definitions may also include modifiers. The simplest field declaration consists of the field type followed by the field name. The type may be preceded by zero or more modifier keywords or annotations (see Chapter 4), and the name may be followed by an equals sign and initializer expression that provides the initial value of the field. If two or more fields share the same type and modifiers, the type may be followed by a comma-separated list of field names and initializers. Here are some valid field declarations:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating and Initializing Objects
Now that we've covered fields and methods, we move on to other important members of a class. Constructors and initializers are class members whose job is to initialize the fields of a class.
Take another look at how we've been creating Circle objects:
Circle c = new Circle();
What are those parentheses doing there? They make it look like we're calling a method. In fact, that is exactly what we're doing. Every class in Java has at least one constructor , which is a method that has the same name as the class and whose purpose is to perform any necessary initialization for a new object. Since we didn't explicitly define a constructor for our Circle class in Example 3-1, Java gave us a default constructor that takes no arguments and performs no special initialization.
Here's how a constructor works. The new operator creates a new, but uninitialized, instance of the class. The constructor method is then called, with the new object passed implicitly (a this reference, as we saw earlier) as well as whatever arguments that are specified between parentheses passed explicitly. The constructor can use these arguments to do whatever initialization is necessary.
There is some obvious initialization we could do for our circle objects, so let's define a constructor. Example 3-2 shows a new definition for Circle that contains a constructor that lets us specify the radius of a new Circle object. The constructor also uses the this reference to distinguish between a method parameter and an instance field of the same name.
Example 3-2. A constructor for the Circle class
public class Circle {
    public static final double PI = 3.14159;  // A constant
    public double r;   // An instance field that holds the radius of the circle

    // The constructor method: initialize the radius field
    public Circle(double r) { this.r = r; }   

    // The instance methods: compute values based on the radius
    public double circumference() { return 2 * PI * r; }
    public double area() { return PI * r*r; }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Destroying and Finalizing Objects
Now that we've seen how new objects are created and initialized in Java, we need to study the other end of the object life cycle and examine how objects are finalized and destroyed. Finalization is the opposite of initialization.
In Java, the memory occupied by an object is automatically reclaimed when the object is no longer needed. This is done through a process known as garbage collection. Garbage collection is a technique that has been around for years in languages such as Lisp. It takes some getting used to for programmers accustomed to such languages as C and C++, in which you must call the free() function or the delete operator to reclaim memory. The fact that you don't need to remember to destroy every object you create is one of the features that makes Java a pleasant language to work with. It is also one of the features that makes programs written in Java less prone to bugs than those written in languages that don't support automatic garbage collection.
The Java interpreter knows exactly what objects and arrays it has allocated. It can also figure out which local variables refer to which objects and arrays and which objects and arrays refer to which other objects and arrays. Thus, the interpreter is able to determine when an allocated object is no longer referred to by any other active object or variable. When the interpreter finds such an object, it knows it can safely reclaim the object's memory and does so. The garbage collector can also detect and destroy cycles of objects that refer to each other, but are not referenced by any other active objects. Any such cycles are also reclaimed.
Different VM implementations handle garbage collection in different ways. It is reasonable, however, to imagine the garbage collector running as a low-priority background thread, so it does most of its work when nothing else is going on, such as during idle time while waiting for user input. The only time the garbage collector must run while something high-priority is going on (i.e., the only time it actually slows down the system) is when available memory has become dangerously low. This doesn't happen very often because the low-priority thread cleans things up in the background.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Subclasses and Inheritance
Content preview·Buy PDF of this chapter|