Cover | Table of Contents | Colophon
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
\u
xxxx. That is, a
backslash and a lowercase u, followed by four hexadecimal
characters. For example, \u0020 is the space
character, and \u03c0 is the character π. You can use Unicode characters anywhere in a Java program,
including comments and variable names.
// and
continues until the end of the current line. For example:
int i = 0; // Initialize the loop variable
/* and continues, over any
number of lines, until the characters */. Any
text between the /* and the
*/ is ignored by the Java compiler. Although
this style of comment is typically used for multiline comments,
it can also be used for single- line comments. This
type of comment cannot be nested (i.e., one /*
*/ comment cannot appear within another one). When
writing multiline comments, programmers often use extra
* characters to make the comments stand out. Here is a typical multiline comment:
/* * Step 4: Print static methods, both public and protected, * but don't list deprecated ones. */
/**, it is regarded as
a special doc comment. Like regular multiline comments,
doc comments end with */ and cannot be
nested. When you write a Java class you expect other
programmers to use, use doc comments to embed documentation about
the class and each of its methods directly into the source code. A program named javadoc extracts these
comments and processes them to create online documentation for your
class. A doc comment can contain HTML tags and can use
additional syntax understood by javadoc. For
example:
/** * Display a list of classes, many to a line. * * @param classes The classes to display * @return <tt>true</tt> on success, * <tt>false</tt> on failure. * @author David Flanagan */
_), or a Unicode currency symbol (e.g.,
$, £, ¥). This initial letter can be
followed by any number of letters, digits, underscores, or
currency symbols. Remember that Java uses the Unicode
character set, which contains
quite a few letters and digits other than those in the ASCII
character set. The following are legal identifiers:
i
engine3
theCurrentTime
the_current_time
θ
abstract
|
default
|
if
|
package
|
synchronized
|
assert
|
do
|
implements
|
private
|
| Type | Contains | Default | Size | Range |
|---|---|---|---|---|
boolean
|
true or false
|
false
| 1 bit | NA |
char
| Unicode character |
\u0000
| 16 bits |
\u0000 to \uFFFF
|
byte
| Signed integer | 0 | 8 bits | -128 to 127 |
short
| Signed integer | 0 | 16 bits | -32768 to 32767 |
int
| Signed integer | 0 | 32 bits | -2147483648 to 2147483647 |
long
| Signed integer | 0 | 64 bits | -9223372036854775808 to 9223372036854775807 |
float
|
IEEE 754
floating point
| 0.0 | 32 bits | ±1.4E-45 to ±3.4028235E+38 |
double
| IEEE 754 floating point | 0.0 | 64 bits | ±4.9E-324 to ±1.7976931348623157E+308 |
boolean1.7 // A floating-point literal true // A boolean literal sum // A variable
sum = 1.7
sum = 1 + 2 + 3*1.2 + (4 + 8)/3.0 sum/Math.sqrt(3.0 * 1.234) (int)(sum + 33)
| Statement | Purpose | Syntax |
|---|---|---|
| expression | side effects |
var
=
expr
;
expr
++;
method
();
new
Type
();
|
| compound | group statements |
{
statements
}
|
| empty | do nothing |
;
|
| labeled | name a statement |
label
:
statement
|
| variable | declare a variable |
[final]
type
name
[=
value
]
[,
name
[=
|
modifiers
type
name ( paramlist ) [ throws exceptions ]
Point to represent a data point in the
two-dimensional Cartesian coordinate system. This class can
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. 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
[]. For example:
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[] Point[] points; // Point[] is an array of Point objects
byte arrayOfBytes[]; // Same as byte[] arrayOfBytes byte arrayOfArrayOfBytes[][]; // Same as byte[][] arrayOfArrayOfBytes byte[] arrayOfArrayOfBytes[]; // Ugh! Same as byte[][] arrayOfArrayOfBytes
int[] (a type) and an array of
int (a particular array value). In practice,
it is usually clear from context whether a type or a value is
being discussed. new keyword, just as you do to create an
object. Arrays don't need to be initialized like objects do,
however, so you don't pass a list of arguments between
parentheses. What you must specify, though, is how
big you want the array to be. If you are creating a
byte[], for example, you must specify how
many byte values you want it to hold. Array values have a fixed size in Java. Once an array is created,
it can never grow or shrink. Specify the desired
size of your array as a non-negative integer between square brackets:
& address-of operator or the
* and ->
dereference operators. In Java, primitive types are always handled
exclusively by value, and objects and arrays are always handled
exclusively by reference: the . operator in
Java is more like the -> operator in C
and C++ than like the . operator of those
languages. It is very important to understand that, unlike
pointers in C and C++, references in Java are entirely opaque:
they cannot be converted to or from integers, and they cannot be
incremented or decremented. java, javax, and org.omg. (Sun also defines standard
extensions to the Java platform in packages whose names begin
with javax.) 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. For example,
java.lang contains two more specialized
packages, named java.lang.reflect and
java.lang.ref, and java.util
contains a subpackage, java.util.zip, that
contains classes for working with compressed ZIP archives. String class, for example, is part of the
java.lang package, so its fully qualified name
is java.lang.String. package directive. The
package keyword, if it appears, must be the
first token of Java code (i.e., the first thing other than
comments and space) in the Java file. The keyword should be
followed by the name of the desired package and a semicolon. Consider a file of Java code that begins with this directive:
package com.davidflanagan.jude;
package directive
import directives
package
and import directives, which are not true
statements) must appear within methods, and all methods must
appear within a class definition. public. A public class is
one that is designed for use by other classes in other packages. We'll talk more about public and related
modifiers in Chapter 3. 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, as we'll see in Chapter 3. 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. public static void main(String[] args)
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). 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
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. #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. short,
int, and long types is
platform-dependent, which hampers portability. Circle,
shown in Example 3-1, contains all four types
of 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;
}
}
Circle objects:
Circle c = new Circle();
Circle class in Example 3-1,
Java gave us a default constructor that takes no arguments
and performs no special initialization. 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),
and whatever arguments that are specified between parentheses
passed explicitly. The constructor can use these arguments
to do whatever initialization is necessary. 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 that have the
same name.
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; }
}
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. Circle defined earlier is a simple class
that distinguishes circle objects only by their radii. Suppose, instead, that we want to represent circles that have both
a size and a position. For example, a circle of radius 1.0
centered at point 0,0 in the Cartesian plane is different from
the circle of radius 1.0 centered at point 1,2. To do this, we
need a new class, which we'll call
PlaneCircle. We'd like to add the ability to
represent the position of a circle without losing any of the
existing functionality of the Circle class. This is done by defining PlaneCircle as a
subclass of Circle, so that
PlaneCircle
inherits the fields and methods of its
superclass, Circle. The ability to add functionality to a class by subclassing, or
extending, it is central to the
object-oriented programming paradigm.
PlaneCircle as a subclass of
the Circle class.
public class PlaneCircle extends Circle {
// We automatically inherit the fields and methods of Circle,
// so we only have to put the new stuff here.
// New instance fields that store the center point of the circle
public double cx, cy;
// A new constructor method to initialize the new fields
// It uses a special syntax to invoke the Circle() constructor
public PlaneCircle(double r, double x, double y) {
super(r); // Invoke the constructor of the superclass, Circle()
this.cx = x; // Initialize the instance field cx
this.cy = y; // Initialize the instance field cy
}
// The area() and circumference() methods are inherited from Circle
// A new instance method that checks whether a point is inside the circle
// Note that it uses the inherited instance field r
public boolean isInside(double x, double y) {
double dx = x - cx, dy = y - cy; // Distance from center
double distance = Math.sqrt(dx*dx + dy*dy); // Pythagorean theorem
return (distance < r); // Returns true or false
}
}
Circle class to be part of a package named
shapes. Suppose we plan to implement a number
of shape classes: Rectangle,
Square, Ellipse,
Triangle, and so on. We can give these
shape classes our two basic area() and
circumference() methods. Now, to make it easy
to work with an array of shapes, it would be helpful if all our
shape classes had a common superclass, Shape. If we structure our class hierarchy this way, every
shape object, regardless of the actual type of shape it
represents, can be assigned to variables, fields, or array elements
of type Shape. We want the Shape class to encapsulate whatever
features all our shapes have in common (e.g.,
the area() and
circumference() methods). But our
generic Shape class doesn't represent any real
kind of shape, so it cannot define useful implementations
of the methods. Java handles this situation with
abstract methods. abstract modifier. An
abstract method has no body; it simply has a
signature definition followed by a semicolon. Here are
the rules about abstract methods and the
abstract classes that contain them:
abstract m