Errata

Java Cookbook

Errata for Java Cookbook

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page 3
MacOS 1st paragraph 5th sentence

"Java 1.8" should be "JRE 1.1.8".

Anonymous   
Printed Page 23
last paragraph

First sentence of the last paragraph should read:

Compilation of this program and examination of the resulting class file reveals that the string "Hello, World " does appear, but th
e conditionally printed epigram does not.

Anonymous   
Printed Page 25
Second paragraph

Last sentence of the 2nd paragraph should include the period within the quotes around 'debug', like this:

My Debug class also provides the string "debug." as part of the System.getProperty(), so we can...

Anonymous   
Printed Page 51
GetOptDemo sample output

In the sample output printed in the book from GetOptDemo, the first input file is
lost. For example, in "java GetOptDemo -n a b c" the output of GetOptDemo lists only
b and c as input. File a is lost.

The problem is in GetOpt (not printed in the book), which doesn't return a very
useful value in getOptInd(). Sometimes this is the index of the first input file, but
sometimes it is the index of the second input file. I don't see any way a calling
program can tell the difference, unless the calling program re-reads the previous
arguments again and duplicates a lot of the logic in GetOpt.

Also, the GetOptTest on page 52 looks like it wanted to use different data in the
"badArgs" array, but in the event, badArgs is identical to goodArgs, which leaves the
reader wondering what the point is. Or maybe the intention was to do two runs, not
three, and the middle run got inserted by accident. Anyway, run 2 and run 3 are
identical, since goodArgs and badArgs are the same.

Anonymous   
Printed Page 59
"Solution" for Section 3.3

"Use String concatentation: the + operator. The compiler will contstruct a
StringBuffer for you and use its append() methods."

It is my understanding that when Java appends two Strings together using the
"+" operator, it does not use a StringBuffer. Instead it creates a new
String Object which contains the contents of the Strings being concatenated.
This is why String concatenation is slow.

Anonymous   
Printed Page 59
Section 3.3

The basic rule for when to use Strings and + vs. StringBuffers and append is
that when a String is constructed all at once, it's easier to concatenate
Strings with +. The Java compiler will automatically convert this notation
into StringBuffer objects and append method calls. Therefore, the first,
rather than the third, way shown in Example 3-2 is actually the concise,
real-world way to form Strings.

On the other hand, when a String needs to be formed little-by-little in a
loop, it's much more efficient to use a StringBuffer and the append method
explictly. If a String is formed using n iterations in a loop, using a
String and + will take O(n^2) time, but using a StringBuffer and append will
take just O(n) time. The time savings in this case justifies the awkwardness
of the StringBuffer and append method.

Anonymous   
Printed Page 89
Table 4-1

Jakarta-ORO and Daniel Savarese's ORO libraries are the same thing. It's
just that Jakarta-ORO is the latest version. Details are at
http://jakarta.apache.org/oro/


Anonymous   
Printed Page 98
3rd part of the code sample

System.out.println(input + "--> " + r.sub(input, "daemon"));

it should be

System.out.println(input + "--> " + r.subst(input, "daemon"));

Anonymous   
Printed Page 121
Example 5-1

Comparing the difference of two numbers with epsilon requires that the
magnitude of epsilon change with the magnitude of the numbers being
compared. But the whole purpose of floating point is that the point floats,
that is, the programmer need not keep track of the magnitude of the numbers.

Here's an equals() method that works over a wide range of magnitudes, and
also works with infinities, NaNs, and positive and negative zero:

public static boolean equals(double a, double b) {
return a == b ||
Math.abs(a - b) < EPS * Math.max(Math.abs(a), Math.abs(b));
}

where EPS is a small double such as 1e-12. Knuth gives a much more rigorous
algorithm for approximate floating point equality in The Art of Computer
Programming, but the above code should be adequate for most Java programs.

Anonymous   
Printed Page 160
1st paragraph

The method will fail if there's a change in daylight saving between the first and the
second date. the result of the following lines should be 122:

Date d1 = new GregorianCalendar(1999, 11, 31, 23, 59).getTime();

Date d2 = new GregorianCalendar(2000, 04, 01, 23, 59).getTime();

long diff = d2.getTime() - d1.getTime();
System.out.println("Difference between " + d2 + "
" + (diff / (1000 * 60 * 60 * 24))
+ " days.");

The solution could be something like:

TimeZone t = new SimpleTimeZone(0, "SIMPLE");
GregorianCalendar c1 = new GregorianCalendar(t);
GregorianCalendar c2 = new GregorianCalendar(t);

c1.set(1999, 11, 31, 23, 59);
Date d1=c1.getTime();

c2.set(2000,04,01,23,59);
Date d2 = c2.getTime();

Anonymous   
Printed Page 163
Discussion

The example of 6.10 is a bit misleading, as it fails to point a
serious trap in the result of the Calendars get() method: while
Calendar counts from one for most entries, months start at zero..

Example:

Calendar calendar = new GregorianCalendar(2001,Calendar.DECEMBER,24);
System.out.println("month/day/year: "
+calendar.get(Calendar.MONTH) +"/"
+calendar.get(Calendar.DAY_OF_MONTH)+"/"
+calendar.get(Calendar.YEAR));

outputs "month/day/year: 11/24/2001".

Thus Java celebrates X-mas at 11/24!

Anonymous   
Printed Page 181
Last line of code

The line where the Iterator is created is wrong in the HashMap example.

It says:
Iterator it = h.values().iterator();

with results:
Key Mountain View, CA; Value null
Key White Plains, NY; Value null
Key Mountain View, CA; Value null
Key Mountain View, CA; Value null
Key Redmond, WA; Value null
Key Sebastopol, CA; Value null
Key Los Angeles, CA; Value null

It should be:
Iterator it = h.keySet().iterator();

Anonymous   
Printed Page 196
paragraph under "Problem" for item 7.14

Missing a period at the end of the next-to-last sentence.

Anonymous   
Printed Page 213
Section 8.4

It's rare for a clone() method to declare that it throws
CloneNotSupportedException, and doing so makes it much harder for the users
of the class to copy objects because they must handle the "impossible"
exception. The only time doing so is necessary is if the class itself does
not implement Cloneable although subclasses are allowed to implement
Cloneable, or if the clone() method called on a field may throw a
CloneNotSupportedException.

A more cookbook way to write the clone() method is the following:

public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}

or if some Cloneable fields need to be cloned:

public Object clone() {
ThisClass tc;
try {
tc = (ThisClass) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
if (field != null)
tc.field = (FieldClass) field.clone();
return tc;
}

or if the class itself does not implement Cloneable or it clones a field that
may throw CloneNotSupportedException:

public Object clone() throws CloneNotSupportedException {
ThisClass tc = (ThisClass) super.clone();
if (field != null)
tc.field = (FieldClass) field.clone();
return tc;
}

Anonymous   
Printed Page 215
Section 8.5 Solution

The suggestion "use a finalizer" is very vague. A protected finalizer method
that calls super.finalize() should be provided, but should not be called by
anyone except the garbage collector and the subclass's finalize() method.
Here's a cookbook finalize() method, assuming that cleanUp() is the method
that should be called to release resources, and it can be called multiple
times (once by client code, once by the finalizer).

protected void finalize() throws Throwable {
try {
cleanUp();
} finally {
super.finalize();
}
}

Anonymous   
Printed Page 216
Section 8.6 Discussion 1st paragraph 2nd sentence

The definition of an inner class is incorrect. A nested class (or nested
interface) is one that is declared inside another class or interface. An
inner class is a non-static class declared inside another class. This
terminology is the one used in the latest editions of The Java Language
Specification (2nd) and The Java Programming Language (3rd).

Anonymous   
Printed Page 232
Streams and Readers/Writers: 1st para

The following sentence is a mis-statement:
"Script-based languages like Arabic and Indian languages, and pictographic languages
like Chinese, Japanese and Korean each have many more than 256 characters, the
maximum that can be represented in an eight-bit byte."

The Korean language is NOT an pictographic language like Chinese and Japanese--it is
a phoenetic language with 11 vowels and 14 consonents.

Anonymous   
Printed Page 242
Last paragraph of recipe 9.4

The paragraph refers to the methods copyTestFile() and copyDataFile(), which aren't shown in example 9-1.

Anonymous   
Printed Page 294
Delete2 code example

The sense of the check for success of the delete is reversed.

Where it says

if (!bkup.delete())
System.out.println("** Deleted "+fileName);

the message indicates we are checking for a successful delete().

Therefore the if statement should read:

if (bkup.delete()) //no !

Anonymous   
Printed Page 307
The Communications API Section, 2nd paragraph, 3rd sentence

The phrase "cast the ComPort object" should read "cast the ComPort
reference". A cast applies to the reference that points to the object; the
object pointed to by the reference is unaffected by the cast.

Anonymous   
Printed Page 325
line 8 in the source code

NOTE: this error is also present in the downloadable source code.

it reads:

....
// The modem sends an extra blank line by way of a prompt.
// Here we read and discard it.
xyz String junk = os.readLine();
if (junk.length() != 0) {
System.err.print("Warning unexpected response: ");
System.err.println(junk);
}
....

see the line marked "xyz" -
a) readLine is deprecated, so its use should be avoided
b) object "os" is a PrintStream - these do not conventionally possess a
"readLine" method

btw - I'm using JDK 1.3, and a surprising amount of code is coming up as
deprecated.

Anonymous   
Printed Page 341
First sentence

The CompTest source doesn't appear to be included in the online code examples.

Anonymous   
Printed Page 342
picture and program

I believe there are some problems with recipe 12.4.

First, the y coordinate of Graphics.drawstring() is the
coordinate of the baseline. Therefore, I don't understand
why you are subtracting the leading which is just the
inter-line spacing. If you want the baseline to be centered,
they the y-coordinate should just be "getSize().height / 2".
If you want the text to actually be centered, then I think
you need something like:
(getSize().height - fm.getHeight()) / 2 + fm.getLeading() + fm.getAscent()

In addition, your font picture is, at best, very misleading. The "height" is
equal to "ascent + decent + leading". Check
out the FontMetrics javadoc.

Anonymous   
Printed Page 457
Example 15-10

Use of deprecated method in example 15-10:

bweigand% javac -deprecation Telnet.java

Telnet.java:50: warning: readLine() in java.io.DataInputStream has been deprecated
while ((line = is.readLine()) != null) {
^

Summary of method:
(http://java.sun.com/products/jdk/1.2/docs/api/java/io/DataInputStream.html)

readLine()
Deprecated. This method does not properly convert bytes to characters. As
of JDK 1.1, the preferred way to read lines of text is via the
BufferedReader.readLine() method. Programs that use the DataInputStream class to read
lines can be converted to use the BufferedReader class by replacing code of the form:

DataInputStream d = new DataInputStream(in);

with:

BufferedReader d
= new BufferedReader(new InputStreamReader(in));

Anonymous   
Printed Page 477
In the run method, declaration of clientSocket

The variable clientSocket is declared within the synchronized section, and it appears the scope
is confined to that section as well. So when it is used outside of this section (i.e. within the
next 6 lines below), the compiler flags it with a "cannot resolve symbol" error.

It can be fixed by declaring clientSocket at the top of the try block, and then just assigning the
variable with the synchronized block:

...
try {
Socket clientSocket;
...
synchronized(servSock) {
clientSocket = servSock.accept();
}
...

Anonymous   
Printed Page 490
First line

<APPLET> should be <APPLET (tag attributes follow).

Anonymous   
Printed Page 491
Example 17-1

This example (AppletMethods.java) is not available in the 9780596001704src.zip
file. (There IS a link to the file in the html index.)

Anonymous   
Printed Page 493
Botton of page continuing to page 494 and 495

The full code for SocketApplet.java is missing, in particular the begining lines
where variables are declared. I am not sure whether this omission is a mistake or
delibrate, but it needs to be more clear.

The full code to produce a working example is available on the website.

Anonymous   
Printed Page 520
text below fig. 18.1

this states that the code for another project "would be like fig 18-1 except
that you would need a doGet instead of a doPost."

Fig 18.1, derived from example 18.1 does in fact use a doGet, rather than a
doPost as stated.

Anonymous   
Printed Page 591
1st code line

The line 'import com.darwinsys.util' must be added to the eample MessageNode.java

Anonymous   
Printed Page 625
Table 20.3

In table 20.3 it says that to read a JDBC field into a float, you should use
"getReal()". It should say "getFloat()" instead.

Anonymous   
Printed Page 655
3rd paragraph

paragraph refers to method "text()" yet the code sample uses the method
"characters()" instead.

Anonymous   
Printed Page 659
doRecursive() method

The call to "doNode(n)" should read "doRecursive(n)".

Anonymous   
Printed Page 687
Table 23.3 Javadoc keywords

Keyword @parameter should read @param
(Checked with sun javadoc pages)

Also serializable keywords missing from table.

Anonymous   
Printed Page 696
Last Line

It took me 2 hours to find out that the code for the
manifest-file works only when written with a capital C in Class

So:

NOT: Main-class: HelloWorld
BUT: Main-Class: HelloWorld

Anonymous   
Printed Page 715
Example 24-2 ThreadsDemo2.java

In the public ThreadsDemo2 constructor, a new thread is created and named...

t = new Thread(this);
t.setName(m + " printer thread");

But, the thread is never started!

t.start();

Anonymous   
Printed Page 717
1st bullet point

"Extending Thread is recommended." Doug Lea's authoritative book Concurrent
Programming in Java gives several concrete reasons why implementing
Runnable should be preferred over extending Thread. The consensus among Java
programmers is that creating a new thread should be done by implementing
Runnable, but creating a new *type* of thread should be done by extending
Thread.

Anonymous   
Printed Page 725
Section 24.5 Discussion, 1st para, 2nd sentence

The statement "only one thread at a time is allowed to run the given code"
is true only for static syncronized methods. For non-static methods, any
number of threads may run the given code at the same time, as long as each
of the threads calls the method on a different object. Synchronization locks
are held on objects, not on methods.

Anonymous   
Printed Page 726
2nd to last sentence

"Making the method synchronized means that any invocations of it will wait
if one thread has already started running the method." Again, this is
true only
if the method is static, or if all threads call the method on the same
object. It is not true for non-static methods when different threads call
the method on different objects.

Anonymous   
Printed Page 748
2nd paragraph

Modern JVMs are not interpreters. Although they may interpret some bytecode, much or all of
the bytecode is compiled to native machine language. This means both that Java is not an
"interpreted language" or scripting language such as Perl or JavaScript (which typically have
an "eval" function to evaluate arbitrary expressions at runtime), and that Java programs can
often run as fast as C or C++ programs. For these reasons, the phrase "JVM Interpreter" is
incorrect and misleading.

Anonymous   
Printed Page 749
Section 25.1 Solution, 1st sentence

The .class syntax does not work on any object; it works on any type. The .getClass()
method should be used on objects. Some extra examples would clarify that .class works
on any type, including primitives and arrays:

System.out.println("int class: " + int.class);
System.out.println("String[] class: " + String[].class);

Anonymous   
Printed Page 754
Section 25.3 Solution

java.lang.class.forName("ClassName") should be Class.forName("ClassName"). First,
java.lang is not needed because the classes in that package are automatically imported,
and also the Class class is capitalized. Additionally, using a String literal is a poor
example, because it's always better written as ClassName.class, which is guaranteed not
to throw an exception.

Anonymous   
Printed Page 756
last third of page, following "And if we run it?"

"javac Cookies DemoCooklet"
Should read
"java Cookies DemoCooklet"

Anonymous   
Printed Page 843
32nd line down

The line reads "esacpes for, 74" when it should be "escapes for, 74"

Anonymous