Cover | Table of Contents | Colophon
C:\javasrc>javac HelloWorld.java C:\javasrc>java HelloWorld Hello, World C:\javasrc>
C:\javasrc>javac HelloWorld.java C:\javasrc>java HelloWorld Hello, World C:\javasrc>
http://www.textpad.com), Visual Slick Edit,
and others are low-cost windowed editors (primarily for MS-Windows)
that have some amount of Java recognition built in, and the ability
to compile from within the editor. TextPad has quite a number of file
types that it recognizes, including batch files and shell scripts, C,
C++, Java, JSP (see Section 18.7), JavaScript (a
client-side web technology), and many others. For each of these, it
uses color highlighting to show which part of the file being edited
comprises keywords, comments, quoted strings, and so on. This is very
useful in spotting when part of your code has been swallowed up by an
unterminated /* comment or a missing quote. While
this isn't the same as the deep understanding of Java that a
full IDE might possess, experience has shown that it definitely aids
programmer productivity. TextPad also has a "compile
Java" command and a "run external program" command.
Both of these have the advantage of capturing the entire command
output into a window, which may be easier to scroll than a
command-line window on some platforms. On the other hand, you
don't see the command results until the program terminates,
which can be most uncomfortable if your GUI application throws an
exception before it puts up its main window. Despite this minor
drawback, TextPad is a very useful tool. Other editors that include
color highlighting include
vim
(an enhanced version of the Unix tool
vi, available for MS-Windows and Unix platforms;
see http://www.vim.org), the
ever-popular Emacs editor, and many others.
The JDK software comes with a minimal set of tools. Serious developers are advised to use a professional Integrated Development Environment with JDK 1.2 software. Click on one of the images below to visit external sites and learn more.
http://www.sun.com/forte/ffj/ and the open source version from http://javacook.darwinsys.com. You will get
two files. First is the source code, in a file called
javacooksrc.jar, which you should unzip
someplace convenient or wherever
you like to keep source
code. Second is a file called
com-darwinsys-util.jar, which you need to set in
your CLASSPATH (see Section 2.6) or
JDKHOME/jre/lib/ext directory. The files are
roughly organized in per-chapter directories, but there is a lot of
overlap and cross-referencing. Because of this, I have prepared a
cross-reference file named index-bychapter.html.
There is also a mechanically generated file called
index-byname.html, which you can use if you know
the name of the file you want (and remember that Java source files
almost always have the same name as the public class they contain).
The canonical index file,
index.html, links to both these files.
. Of course, not everybody likes
typing those commands, so there is a makefile for the
make utility. make is
standard on Unix and readily available for MS-Windows from, for
example, the
GNUwin32 project (see http://sourceforge.net/projects/gnuwin32/). There is
also a top-level makefile that visits the subdirectories and runs
make in each of them. These makefiles have been
tested with gmake (GNU make
3.79.1), BSD make (OpenBSD 2.8), and they should
work with almost any reasonably modern make
program or equivalent.
HelloWorld program from the current directory. The
compiler is actually reading a source file, while the
java command is running a class, a class that
might be located someplace in your CLASSPATH (see Section 2.6). It is common for JDK users to use a
batch script or command file to automate
this. Mine is called jr, for Java compile and
Run. The Unix version is jr, a
shell script:
javac $1.java && java $*
$* gets expanded to include
$1 and any other arguments. The
MS-Windows version is jr.bat
:
javac %1.java if errorlevel 1 goto norun java %1 %2 %3 %4 %5 %6 :norun
all:
javac HelloWorld.java#) are
comments for the reader and are
ignored by make :
# Makefile for Acme FlutterBox program.
# Uncomment one of these compiler definitions:
#JAVAC= javac
JAVAC= jikes +E
compile:
$(JAVAC) *.java
clean:
@rm -f *.class http://jakarta.apache.org/ant/. Like
make, Ant uses a file or files -- written in
XML -- listing what to do and, if
necessary, how to do it. These rules are intended to be
platform-independent, though you can of course write
platform-specific recipes if necessary.
<project name="Java Cookbook Examples" default="compile" basedir=".">
<!-- set global properties for this build -->
<property name="src" value="."/>
<property name="build" value="build"/>
<!-- Specify the compiler to use.
Using jikes is supported but requires rt.jar in classpath. -->
<property name="build.compiler" value="modern"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<!-- specify what to compile. This builds everything -->
<target name="compile" depends="init">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"
classpath="../com-darwinsys-util.jar"/>
</target>
</project>$ ant compile Buildfile: build.xml Project base dir set to: /home/ian/javasrc/starting Executing Target: init Executing Target: compile Compiling 19 source files to /home/ian/javasrc/starting/build Performing a Modern Compile Copying 22 support files to /home/ian/javasrc/starting/build Completed in 8 seconds $
java.applet.Applet, and in doing so inherits the
functionality it needs to be viewable inside a web page in a
Java-enabled web
browser. All
that's necessary is an HTML page referring to the applet. This
HTML page requires a minimum of three
attributes
, or modifiers: the applet itself, and
the width and height it needs on-screen, in screen dots or pixels.
This is not the place for me to teach you the syntax of
HTML -- there is some of that in Section 17.2 -- but I'll show my HTML applet
template file. Many of the IDEs will write a page like
this for you if you use their "build new applet" wizards.
<HTML> <HEAD><TITLE>A Demonstration</TITLE></HEAD> <BODY> <H1>My TEMPLATE Applet</H1> <APPLET CODE="CCC.class" WIDTH="200" HEIGHT="200"> </APPLET> </BODY> </HTML>
Appletviewer
, a kind of mini-browser. You need to give
it the HTML file, just like a regular browser. Sun's
AppletViewer (shown in Figure 1-12 under MS-Windows) has an explicit
reload button that actually reloads the applet. And it has other
features such as debugging hooks and other information displays. It
also has a View->Tag menu that lets you resize the window until
the applet looks best, and then you can copy and paste the
tag -- including the adjusted WIDTH and HEIGHT tags -- into a
longer HTML document.
java.util.Date
class
had some serious limitations with regard to internationalization.
Accordingly, many of the Date class methods and
constructors are marked "deprecated." To
deprecate something means, according to my
Concise Oxford Dictionary of Current English,
to "express wish against or disapproval of." Java's
developers are therefore expressing a wish that you no longer do
things the old way. Try compiling this code:
import java.util.Date;
/** Demonstrate deprecation warning */
public class Deprec {
public static void main(String[] av) {
// Create a Date object for May 5, 1986
// EXPECT DEPRECATION WARNING
Date d = new Date(86, 04, 05); // May 5, 1986
System.out.println("Date is " + d);
}
}C:\javasrc>javac Deprec.java Note: Deprec.java uses or overrides a deprecated API. Recompile with "-deprecation" for details. 1 warning C:\javasrc>
-deprecation
for details:
C:\javasrc>javac -deprecation Deprec.java
Deprec.java:10: warning: constructor Date(int,int,int) in class java.util.Date has
been deprecated
Date d = new Date(86, 04, 05); // May 5, 1986
^
1 warning
C:\javasrc>Date constructor that
takes three integer arguments has been deprecated. How do you fix it?
The answer is, as in most questions of usage, to refer to the
Javadoc documentation for the class. In Java
2, the introduction to the if statement
whose value is known to be false at compile
time. Why should it even generate code for the
condition? True, you say, but how can the results of an
if statement be known at compile time? Simple:
through final
boolean variables.
Further, if the value of the if condition is known
to be false, then the body of the if statement
should not be emitted by the compiler either. Presto -- instant
conditional compilation!
// IfDef.java
final boolean DEBUG = false;
System.out.println("Hello, World ");
if (DEBUG) {
System.out.println("Life is a voyage, not a destination");
}Debug class.if statement is not all that great. Let's
combine the flexibility of runtime checking with the simple
if statement to debug a hypothetical
fetch( ) method
(part of Fetch.java):
String name = "poem";
if (System.getProperty("debug.fetch") != null) {
System.err.println("Fetching " + name);
}
value = fetch(name);-D argument to enable
debug.fetch, the printout will occur:
> java Fetch # See? No output > java -Ddebug.fetch Fetch Fetching poem >
if statement is tedious to
write in large quantities, so I have encapsulated it into a
Debug
class, which is part of my
com.darwinsys.util package.
Debug.java appears in full at the end of this
chapter, in Section 1.19. My Debug
class also provides the string "debug". as part of the
System.getProperty(
)
, so we can simplify the previous
Fetch example as follows (code in
FetchDebug.java):
String name = "poem", value;
Fetch f = new Fetch( );
Debug.println("fetch", "Fetching " + name);
value = f.fetch(name); Fetch:
> java FetchDebug # again, no output > java -Ddebug.fetch FetchDebug Fetching poem >
/** This program exhibits some bugs, so we can use a debugger */
public class Buggy {
static String name;
public static void main(String[] args) {
int n = name.length( ); // bug # 1
System.out.println(n);
name += "; The end."; // bug #2
System.out.println(name); // #3
}
}ian> java Buggy
Exception in thread "main" java.lang.NullPointerException
at Buggy.main(Compiled Code)
ian> jdb Buggy
Initializing jdb...
0xb2:class(Buggy)
> run
run Buggy
running ...
main[1]
Uncaught exception: java.lang.NullPointerException
at Buggy.main(Buggy.java:6)
at sun.tools.agent.MainThread.runMain(Native Method)
at sun.tools.agent.MainThread.run(MainThread.java:49)
main[1] list
2 public class Buggy {
3 static String name;
4
5 public static void main(String[] args) {
6 => int n = name.length( ); // bug # 1
7
8 System.out.println(n);
9
10 name += "; The end."; // bug #2
main[1] print Buggy.name
Buggy.name = null
main[1] help
** command list **
threads [threadgroup] -- list threads
thread <thread id> -- set default thread
suspend [thread id(s)] -- suspend threads (default: all)
resume [thread id(s)] -- resume threads (default: all)
where [thread id] | all -- dump a thread's stack
wherei [thread id] | all -- dump a thread's stack, with pc info
threadgroups -- list threadgroups
threadgroup <name> -- set current threadgroup
print <id> [id(s)] -- print object or field
dump <id> [id(s)] -- print all object information
locals -- print all local variables in current stack frame
classes -- list currently known classes
methods <class id> -- list a class's methods
stop in <class id>.<method>[(argument_type,...)] -- set a breakpoint in a method
stop at <class id>:<line> -- set a breakpoint at a line
up [n frames] -- move up a thread's stack
down [n frames] -- move down a thread's stack
clear <class id>.<method>[(argument_type,...)] -- clear a breakpoint in a method
clear <class id>:<line> -- clear a breakpoint at a line
step -- execute current line
step up -- execute until the current method returns to its caller
stepi -- execute current instruction
next -- step one line (step OVER calls)
cont -- continue execution from breakpoint
catch <class id> -- break for the specified exception
ignore <class id> -- ignore when the specified exception
list [line number|method] -- print source code
use [source file path] -- display or change the source path
memory -- report memory usage
gc -- free unused objects
load classname -- load Java class to be debugged
run <class> [args] -- start execution of a loaded Java class
!! -- repeat last command
help (or ?) -- list commands
exit (or quit) -- exit debugger
main[1] exit
ian>http://www.extremeprogramming.org) advocate
writing the unit tests before you write the
code, and also advocate running your tests almost every time you
compile. This group of extremists has some very well-known leaders,
including Gamma and Beck of Design Patterns
fame. While I am not yet ready to unconditionally endorse all aspects
of Extreme Programming, I certainly go along with their advocacy of
unit testing.
main
method that just
tests out the functionality of the class. Here is an
example:
/** A simple class used to demonstrate unit testing. */
public class Person {
protected String fullName;
protected String firstName, lastName;
/** Construct a Person using his/her first+last names. */
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
/** Get the person's full name */
public String getFullName( ) {
if (fullName != null)
return fullName;
return firstName + " " + lastName;
}
/** Simple test program. */
public static void main(String[] argv) {
Person p = new Person("Ian", "Darwin");
String f = p.getFullName( );
if (!f.equals("Ian Darwin"))
throw new IllegalStateException("Name concatenation broken");
System.out.println("Fullname " + f + " looks good");
}
}^H^@Z^C^@^@^@P^H^@[^H^@n^H^@o^H^@p^H^@q^H^@r^H^@s^H^@t^H^@v^H^@y^H
^@z^H^@{^H^@}^H^@Ç^H^@ä^H^@à^H^@á^H^@ª^H^@º^G^@ç^G^@Æ^G^@ô^G^@ö^G^@ò^G^@Û^G^@ù^G
^@ÿ^G^@...^G^@Ü^G^@¢^G^@£^G^@¥
^@^V^@@
^@^\^@@
^@!^@A
^@^Y^@B
^@^[^@Cobfuscator
.
An obfuscator takes your program and tries to make it obscure, so
that decompilation either will not work or will not be useful.
catch
clause that matches it. If none is
found, the Java interpreter program catches it and prints a stack
traceback showing all the method calls that got from the top of the
program to the place where the exception was thrown. You can print
this traceback yourself in any catch clause: the
Throwable
class has several methods called
printStackTrace( ).
C:\> set JAVA_COMPILER=NONE # DOS, MS-Windows setenv JAVA_COMPILER NONE # UNIX Csh export JAVA_COMPILER=NONE # UNIX Ksh, modern sh
http://java.oreilly.com). What I didn't
tell you, but what you might have realized by extension, is that the
source examples from all the O'Reilly Java
books are available there too: the Java Examples in a
Nutshell book; the Java Swing
book; all of them.
java.util.ArrayList actually works? You have the
source code. Got a problem making a JTable behave?
Sun's JDK includes the source for all the public classes! Look
for a file called src.zip or src.jar
; some versions unzip this and some do not.
java.io.Reader has a method
called read(
)
, which reads bytes of data from a file
or network connection. This is written in C because it actually calls
the read( ) system call for Unix, MS-Windows,
MacOS, Palm, BeOS, or whatever. The JDK source kit includes the
source of all this stuff.
Debug utility mentioned in Section 1.12.
package com.darwinsys.util;
/** Utilities for debugging
*/
public class Debug {
/** Static method to see if a given category of debugging is enabled.
* Enable by setting e.g., -Ddebug.fileio to debug file I/O operations.
* Use like this:<BR>
* if (Debug.isEnabled("fileio"))<BR>
* System.out.println("Starting to read file " + fileName);
*/
public static boolean isEnabled(String category) {
return System.getProperty("debug." + category) != null;
}
/** Static method to println a given message if the
* given category is enabled for debugging.
*/
public static void println(String category, String msg) {
if (isEnabled(category))
System.out.println(msg);
}
/** Same thing but for non-String objects (think of the other
* form as an optimization of this).
*/
public static void println(String category, Object stuff) {
println(category, stuff.toString( ));
}
}System class,
which knows a lot about our system.
java.lang.Runtime, lies behind many of the methods
in the System class. System.exit(
), for example, just calls Runtime.exit(
). This is technically part of "the
environment," but the only time we use it directly is to run
other programs, which is covered in Section 26.2. The
java.awt.Toolkit object is also part of the
environment and is discussed in Chapter 12.
static
method called getenv( ) in class
java.lang.System . Let's try it out. But
remember, you made me do it. First, the code. All we need is this
line in a main program:
System class,
which knows a lot about our system.
java.lang.Runtime, lies behind many of the methods
in the System class. System.exit(
), for example, just calls Runtime.exit(
). This is technically part of "the
environment," but the only time we use it directly is to run
other programs, which is covered in Section 26.2. The
java.awt.Toolkit object is also part of the
environment and is discussed in Chapter 12.
static
method called getenv( ) in class
java.lang.System . Let's try it out. But
remember, you made me do it. First, the code. All we need is this
line in a main program:
System.out.println("System.getenv(\"PATH\") = " + System.getenv("PATH"));C:\javasrc>javac GetEnv.java Note: GetEnv.java uses or overrides a deprecated API. Recompile with -deprecation for details.
C:\javasrc>javac -deprecation GetEnv.java
GetEnv.java:9: Note: The method java.lang.String getenv(java.lang.String) in class
java.lang.System has been deprecated.
System.out.println("System.getenv(\"PATH\") = " + System.getenv("PATH"));
^
Note: GetEnv.java uses or overrides a deprecated API. Please consult the
documentation for a better alternative.
1 warningSystem.getProperty(
)
or System.getProperties(
).
java.util.Properties object, which
we'll discuss more fully in Section 7.8. So if
I chose to, I could store the following properties in a
Properties object called ian:
name=Ian Darwin favorite_popsicle=cherry favorite_rock group=Fleetwood Mac favorite_programming_language=Java pencil color=green
Properties
class has several forms of its retrieval
method. You could, for example, say
ian.getProperty("pencil
color")
and get back the string "green". You can also provide a
default: say ian.getProperty("pencil color",
"black"), and if the property has not been set you would
get the default value "black".
System
class
and its role as keeper of the particular
Properties object that controls and describes the
Java runtime. The System class has a static
Properties member whose content is the merger of
operating system specifics
(os.name, for example), system and user tailoring
(java.class.path), and properties defined on the
command line (as we'll see in a moment). Note that the use of
periods in these names (like os.arch,
os.version and java.class.path,
java.lang.version) makes it look as though there
is a hierarchical relationship similar to that for class names. The
Properties class, however, imposes no such
relationships: each key is just a string, and dots are not special.
System.getProperty( ). If you want them all, use
System.getProperties( ). Accordingly, if I wanted
to find out if the System
Properties had a property named "pencil
color", I could say:
String color = System.getProperty("pencil color");System.getProperty(
):
System.out.println(System.getProperty("java.specification.version"));Class.forName("class")
, which throws an
exception if the class cannot be loaded -- a good indication that
it's not present in the runtime's library. Here is code
for this, from an application wanting to find out whether the JDK 1.1
or later components are available:
/** Test for JDK >= 1.1 */
public class TestJDK11 {
public static void main(String[] a) {
// Check for JDK >= 1.1
try {
Class.forName("java.lang.reflect.Constructor");
} catch (ClassNotFoundException e) {
String failure =
"Sorry, but this version of MyApp needs \n" +
"a Java Runtime based on Java JDK 1.1 or later";
System.err.println(failure);
throw new IllegalArgumentException(failure);
}
System.out.println("Happy to report that this is JDK1.1");
// rest of program would go here...
return;
}
}Class.forName("javax.swing.JButton");System.properties.
-). And the
PATH separator (:)
was also used as a "drive letter" delimiter, as in C: or
A:. So we now have commands like this:
|
System
|
Directory list command
|
Meaning
|
Example PATH setting
|
|---|---|---|---|
|
Unix
|
ls -R /
|
Recursive listing of /, the top-level directory
|
PATH=/bin:/usr/bin
|
|
DOS
|
dir/s \ |
java -classpath \c:\ian\classes MyProg
trace,
strace, truss,
ktrace) you would probably see the Java
program open (or stat, or
access) the following files: