Historical record of pre-2008 errata:
Here's a key to the markup:
[page-number]: serious technical mistake
{page-number}: minor technical mistake
<page-number>: important language/formatting problem
(page-number): language change or minor formatting problem
?page-number?: reader question or request for clarification
Confirmed errors:
(Back Cover) End of second paragraph;
"error-prone" should be changed to "error-proof"
(xiv):
"I take my hat of to"
should read
"I take my hat off to"
(xv):
"Copyright 2001 O'Reilly"
should read
"Copyright 2004 O'Reilly"
(xvi) Replace Paragraph
I would like to take a moment to say �Hi� to my brother Paul and my sister Debbie. I
currently live in Germany, and although I am very happy living here, I miss my brother
and sister greatly.
with
I would also like to thank my new wife Alma for being the wonderful person she is and
supporting me through all of my efforts to write and maintain this book.
In addition, I would like to thank all of my readers from all over the world who have
submitted errata. Your vigilance has helped refine my work and kept me honest. I look
forward to your feedback, concerns and questions.
(4) First bullet point at the top of the page. Second sentence.;
"This means that all the objects that are be stored in collection classes ultimately
have to descend from one class."
Should be:
"This means that the classes of all the objects that are to be stored in collections
must descend from one class."
(4):
"Example 1-4 shows the getclass() method in action"
should read
"Example 1-4 shows the getClass() method in action"
(5):
"b = (A) a1; // compiler error: a1 is not a B"
should read
"b = (B) a1; // compiler error: a1 is not a B"
Same in the compilation trace a little further on the same page
(5) Middle of the compilation output
[javac] b = (A)a1; // compiler error: a1 is not a B.
should read
[javac] b = (B)a1; // compiler error: a1 is not a B.
(6) Last paragraph
because the evaluation of the if statement is abbreviated at runtime.
Should read
because the evaluation of the condition within the if statement is abbreviated at runtime.
(7) After the end of the first paragraph, add the following inset note:
The abbreviation of the evaluation in this if statement isn�t unique to the if statement. In
fact it is actually a property of the && operator itself. Many other conditional evaluation
operators such as || will short circuit in evaluation as well. Once the evaluation reaches a
point where subsequent evaluations cant change the value of the evaluation, the computer stops
processing the evaluation.
(Note that the operators && and || in constant width font. )
(7) Second to last paragraph
Ternary statements
Should be
Ternary expressions
(9) Last paragraph
The allocation statement in the for loop is executed when the loop is set up. At each iteration
of the loop, the expression in the middle is evaluated and, if the expression is true, the
iteration statement is run.
Should read
The allocation statement in the for loop is executed when the loop is set up. At each iteration
of the loop, the expression in the middle is evaluated. Each time the expression is evaluated as
being true, with the exception of the first time, the iteration statement is run.
(12):
"Finally, if she inputs anything else, the result will be Option 4"
should read
"Finally, if the user inputs anything else, the result will be Option 3">
(12) last paragraph;
Without the break, you would always get "Option 4"
Should be
Without the break, you would always get "Option 3"
(12 + 13) code samples showing break usage;
There are one too many closing braces in all three of the code samples in this
section (decode, decode, and matrixMeth).
(12) last paragraph;
Should be "Option 3" instead of
"Option 4" in "Finally, if she inputs anything else, the result will be "Option 4"."
Same thing in
"Without the break, you would always get "Option 4" as the result of the method..."
(14) First paragraph
However, the break statement doesn�t do this. It merely breaks out of its current loop.
Should read:
However, the break statement doesn�t do this. It merely breaks out of the block in which
it is contained, which in this case happens to be the innermost loop.
{14} First Code Snippet (only code snippet)
Replace entire snippet with the following code.
package oreilly.hcj.review;
public class SyntaxIssues {
public static void continueFunc() {
int complex = 0;
int processing = 0;
for (int idx = 0; idx < 1000; idx++) {
// ... do some complex code.
complex++;
if (idx == 555) {
break;
}
// ... processing code
processing++;
}
System.out.println(" Complex: " + complex);
System.out.println("Processing: " + processing);
System.out.println("------------------------------");
complex = 0;
processing = 0;
for (int idx = 0; idx < 1000; idx++) {
// ... do some complex code.
complex++;
if (idx == 555) {
continue;
}
// ... processing code
processing++;
}
System.out.println(" Complex: " + complex);
System.out.println("Processing: " + processing);
}
}
{14} Second to last paragraph
In the first loop, the processing code is executed only 554 times.
it should say:
In the first loop, the complex code is executed 556 times whereas the processing code
is executed only 555 times.
{14} Second to last paragraph
However, in the second loop the processing code is executed 999 times.
Should say
However, in the second loop the complex code is executed 1000 times
while the processing code is executed only 999 times.
(15) Paragraph right before the last code sample.
Replace the paragraph
Once you have declared the label, you can use it in a break or a continue statement.
The following code shows how you can use break to repair a faulty matrix:
With the following text
Once you have declared the label, you can use it in a break or a continue statement
to exert more control over how they work. The following code demonstrates how you
can use break to exit out of deeply nested loops:
(15) Note on the page
Change the word
semantics
To
Scope
(15) Last code snippet:
Replace all occurrences of
RESTART
With
PROCESS_LOOP
[15 -16] Final paragraph (starts on 16 and ends on 17)
Replace the paragraph
In this version, if an error condition is detected, the method will try to repair the
error condition and then start to process the matrix all over again. This is accomplished
by the break RESTART; statement. This statement tells the virtual machine to immediately
transfer control to the statement labeled RESTART. This will work only if the break statement
is nested inside the labeled statement. Otherwise, the compiler will just laugh at you
sardonically and tell you that the label RESTART isn�t declared.
With the following text
In this method, if any of the Points in the matrix contain a negative number for the x or y
attribute, the break statement will cause the virtual machine to exit the block labeled by
the PROCESS_LOOP label. This will work only if the break statement is nested inside the
labeled statement. Otherwise, the compiler will tell you that the label PROCESS_LOOP isn�t
declared.
{16} First code snippet
Replace entire code snippet with the following code.
package oreilly.hcj.review;
public class SyntaxIssues {
public static void matrixMeth3(final Point[][] values) {
int ctr = 0;
LINE: for (int x = 0; x < values[0].length; x++) {
COLUMN: for (int y = 0; y < values.length; y++) {
LOGLINE: System.out.println(values[x][y].toString());
if ((values[x][y].x < 0) || (values[x][y].y < 0)) {
continue LINE; // skip the rest of the line;
}
// do something with the value
ctr++;
}
}
System.out.println("Elements processed: " + ctr);
// continue processing
PASS_TWO: for (int x = 0; x < values[0].length; x++) {
// do some code.
}
}
}
<17> First paragraph, last two sentences
Replace
The assert keyword has two forms. The first form of assertion uses the following grammar:
With the text
An assertion uses the following grammar:
<17> First code snippet
Replace
assert Boolean_Expression;
With
assert Boolean_Expression [ : Detail_expression];
<17> Second paragraph
Replace
In this form, Expression is replaced by an expression that evaluates to a boolean result. If
the result is false, then an AssertionError will be thrown by the compiler:
With
The Detail_Expression is optional and the Boolean_Expression is replaced by an expression
that evaluates to a boolean result. If the result is false, then an AssertionError will be
thrown by the compiler:
<17> Third paragraph, last sentence
Replace
If the developer of the method wants to provide an error message, he could have used the
second form of assert:
With
If the developer of the method wants to provide an error message, he can use provide a
non-void expression for Detail_Expression:
{18} 1st paragraph;
Replace the paragraph
An attempt to do something like this would be rejected by the compiler since the evaluation
of the expression is void. Similarly, any method that returns void is off limits as well.
With the paragraph
An attempt to do something like this would be rejected by the compiler since the code is not
an expression but rather an assignment.
{19} 2nd code sample;
The first two lines should be deleted:
package oreilly.hcj.review;
public class Assertions {
Instead, the code should start with the 2nd "package" line.
(20) 2nd paragraph (with the "note" icon);
Change
Its better to use assertions so that programs can at least limp along...
To
It is better to use assertions so that programs can at least limp along...
(20):
In the third bullet,
"... that it will never to return null to the user"
should read
"... that it will never return null to the user"
(23) 1st paragraph;
Should be "lose" instead of "loose" in
"Although you will loose some performance and incur a few crashes..."
(25) Second paragraph.
Remove the sentence that reads
I have yet to understand why this limitation is in Java, but it does indeed exist.
(29) Third paragraph after second code snippet
Replace the entire paragraph
In this code, you have created a constant without giving the constant a value. Perhaps
the value you want requires more complex code than a simple assignment. This is where
the special static{} method comes in. The ClassLoader automatically invokes all static{}
initializer methods when the class is loaded into the virtual machine. It is in this
method only that you can initialize final static variables that are not initialized on
their declaration line. You can use this method in a similar manner as the method-based
instance initializers:
with the following text (I have made some language changes and added text)
In this code, you have created a constant without giving the constant a value. Perhaps
the value you want requires more complex code than a simple assignment. This is where
the special static{} initializer comes in. The ClassLoader automatically invokes all static{}
initializers when the class is loaded into the virtual machine. It is in this method only
that you can initialize final static variables that are not initialized on their declaration
line. Furthermore, you can use static{} to initialize non-final static variables as well. You
can use this method in a similar manner as the method-based instance initializers:
(30) Last paragraph before the code output.
Replace
When the example is run, the static nested class Ranges is initialized first. As a result,
you will see the following output:
With the following text:
When the example is run, you might expect that the static nested class Ranges is initialized
completely first. However, this is not the case and as a result, you will see the following output:
(34):
On the fourth line,
"handleOKbtn()"
should read
"handleOKBtn()"
(34) The paragraph right after the note
Add the following text to the end of the paragraph:
However, you should be aware that protected members are also accessible to classes
within the same package. Although this is unfortunate, most of the time it shouldn�t
be too dangerous as packages should usually be developed as an encapsulation unit themselves.
(38) Paragraph under the heading �Common Mistakes�
There are a certain group of mistakes
Should read
There is a certain group of mistakes
{39}: Mispaced patentheses in catch clause and missign parameter:
public void someMethod() {
try {
// do a whole bunch of stuff
} (catch IllegalAccessException ex) {
throw new MyApplicationException();
}
}
should be
public void someMethod() {
try {
// do a whole bunch of stuff
} catch (IllegalAccessException ex) {
throw new MyApplicationException(ex);
}
}
(43) First paragraph
Replace the paragraph
One fundamental principle of programming is that, generally, it is best to swap a logic
error for a compiler error. Compiler errors tend to be found in seconds and are corrected
just as fast. Syntax errors are a good example. A missing semicolon can make things
confusing. If the compiler error is something particularly cryptic, the resolution may
take as long as a couple of minutes to discover.
With the text:
One fundamental principle of programming is that, generally, it is best to swap a logic
error for a compiler error. Compiler errors, such as missing semicolons, tend to be found
in seconds and are corrected just as fast. Occasionally a compiler error is something
particularly cryptic which may take as long as a couple of minutes to discover and repair.
(46) 1st paragraph, which immediatly follows the code sample which starts the page;
Therefore, the following two lines are identical from the point of view of the compiler:
public final static String A_STRING = "Hardcore Java";
public final static String A_STRING = "Hardcore"+ "Java";
The second line is missing a space, and should be:
public final static String A_STRING = "Hardcore "+ "Java";
[53] Section Chaining Finals;
Remove entire section!
(54):
In example 2-9, it would be wise to mention that the final modifier does
not protect the parameter (which is passed by value), but it protects its
use in the computation of the method.
{56}: Caption for example 2-12 and its continuation on the next page
Replace
nonimmutable
with
mutable
(58) End of Paragraph 2;
The word "UnmodifableCollection" should read "UnmodifiableCollection"
{59} last paragraph;
the text -
When you call Collections.unmodifiableSet(), the class creates a new
instance of this static nested class and sets the source collection as the
delegate object. As you can see in the example code from the JDK, the
class UnmodifiableSet implements java.util.Set and inherits from
UnmodifiableCollection, which in turn implements java.util.Collection.
Should be changed to -
When you call Collections.unmodifiableSet(), the class creates a new
instance of the static nested class UnmodifiableSet and sets the source
collection as the delegate object. The class UnmodifiableSet, which is
similar to the UnmodifiableCollection class shown in the
example, implements java.util.Set and inherits from
UnmodifiableCollection, which in turn implements java.util.Collection.
{60} First paragraph;
The Text:
------
This delegate structure also plugs another big hole: if the UnmodifiableSet class
inherited from HashSet, then the user could just cast the instances back to HashSet
to gain access to write methods. The delegate structure in the JDK quite elegantly
blocks this, ensuring that an UnmodifiableSet truly is unmodifiable, even when placed
in the hands of a clever and sneaky programmer.
-----
Should be removed. You cant cast something to something it isnt. In this case casting
it up would not result in the methods of the superclass beign called since all
methods in java are virtual.
{75}:
Use IllegalArgumentException instead of NullPointerException (see class comment for NullPointerException)
{91} Caption for Example 4-1
Replace
An age Comparator
Change to
A Tax ID Comparator
(92) In the note at the bottom of the page;
The formula for calculating log[base 2](n) should read
"log[base 2](n) = log[base10](n)/log[base 10](2)"
not
"log[base 2](n) - log[base 10](n)/log[base 10](2)".
The minus sign should be an equals sign.
(93) Last paragraph before the heading that reads �Lists�
Remove the following sentence
Generally, algorithms higher than O(n) are not feasible as solutions to practical problems.
(95) 2nd paragraph in section "java.util.ArrayList";
"...you should choose a list class."
should be:
"...you should choose ArrayList."
(97) Second to last paragraph
After the following sentence:
As you insert new items into the table, the hash code of the object is used to determine
which bucket the object should go into.
Insert this sentence:
The algorithm that determines which bucket to put the object into takes the modulus of
the hash code and the number of buckets.
[98] Figure 4-3
Replace entire figure with this one - examples.oreilly.com/hardcorejv/Hashtable.png
{102} 2nd paragraph;
heading
java.util.LinkedSet
should be
java.util.LinkedHashSet
{102} Paragraph 2
LinkedSet
Should be
LinkedHashSet
(103):
On figure 4-5, "<<extend>> Key/Value Storage" should be added as a label
of the relationship between the Use Map and the Collection Decision use cases.
(105):
"...and these reverences..."
should read
"...and these references..."
(105) Last paragraph on 105 extending to 106
Change the sentences:
However, if you create a lot of objects, it is likely that they will be close to
each other within the memory. The result would be a HashMap with most of the objects
in the first bucket and few, if any, in the other buckets.
To read:
However, the default hashCode() method does not guarantee that the hash codes will
be well distributed. Therefore, if you rely on the default hashCode() method, the
result may be a HashMap with most of the objects in the first bucket and few, if
any, in the other buckets.
(108):
"If this technique adopted as a..."
should read
"If this technique is adopted as a..."
{117}:
In the first code example,
"reflectionMethod3"
should be
"reflectionMethod4"
(117): In the paragraph before Example 5-3,
"RuntimExceptions"
should read
"RuntimeExceptions"
<121> Replace entire contents of example 5-5 with the following code.
package oreilly.hcj.exceptions;
public class MyCustomException extends Exception {
/** Constant for a transaction error. */
public static final int NO_RESERVATION = 0;
/** Constant for a transaction error. */
public static final int TRANSACTION_ERROR = 1;
/** Constant for a billing error. */
public static final int BILLING_ERROR = 2;
/** Constant for credit card declined. */
public static final int CREDIT_CARD_DECLINED = 3;
/** The type of exception. */
final int type;
/**
* Creates a new MyCustomException object.
*
* @param type The type of error.
*
* @throws IllegalArgumentException If the type given is invalid.
*/
public MyCustomException(final int type) {
if ((type != NO_RESERVATION) && (type != TRANSACTION_ERROR)
&& (type != BILLING_ERROR) && (type != CREDIT_CARD_DECLINED)) {
throw new IllegalArgumentException();
}
this.type = type;
}
/**
* Get the exception type.
*
* @return type The exception type.
*/
public int getType() {
return this.type;
}
}
(121) Paragraph immediately following example 5-5
Replace the paragraph
If you declare a new exception class, make sure that the exception is fundamentally
different than the other exceptions. Also, make sure that there isn�t already an exception
for the type of exception you need. For example, you shouldn�t declare a business logic
exception type for null pointers, but use NullPointerException instead.
With the folowing paragraphs:
Grouping together exceptions of similar type is much more efficient than declaring a
different exception for every possible error in the program. Instead of declaring hundreds
of exceptions, look for broad categories of exceptions such as GUIException,
AccountingException and AuthorizationException. Inside these exception types, you can
declare specifiers to provide more information on the exception.
Furthermore, you should make sure that there isn�t already an exception for the type
of problem that you wish to indicate. For example, you shouldn�t declare a business
logic exception type for null pointers, but use NullPointerException instead.
<121> Replace the note on the page with the following note
In declaring specifiers for MyCustomException, I created integral constants. Instead it
would be far better to use constant objects as specifiers to MyCustomException. We will
talk about constant objects in Chapter 7 and revisit the custom exception class.
(122):
"In the try-catch-finally triad, is the finally clause is often..."
should read
"In the try-catch-finally triad, the finally clause is often..."
(123) Last but one paragraph;
Change
"The catch clause is this example .."
to
"The catch clause in this example .."
[125] Middle of example 5-7
The lines:
for (idx = 0; idx < columnCount; idx++) {
record[idx] = rs.getObject(idx);
}
should read:
for (idx = 0; idx < columnCount; idx++) {
record[idx] = rs.getObject(idx + 1);
}
{126} Code snippet;
The lines:
for (idx = 0; idx < columnCount; idx++) {
record[idx] = rs.getObject(idx);
should read:
for (idx = 0; idx < columnCount;) {
record[idx] = rs.getObject(idx + 1);
[127] Code snippet;
The lines:
for (idx = 0; idx < columnCount; idx++) {
record[idx] = rs.getObject(idx);
}
should read:
for (idx = 0; idx < columnCount;) {
record[idx] = rs.getObject(++idx);
}
<129> Last paragraph
Remove all content starting with the paragraph that reads:
However, there is still a problem with your exceptions. The fact that the firePropertyChange( )
and the methods called after it can cause runtime exceptions
Until the end of the chapter. I have reconsidered these paragraphs in light of reader comments and they
need to go as they present an inconsistency with chapter 6 warning against masking exceptions.
The chapter should end after the second to last paragraph on page 129.
(131) first paragraph, fourth sentence;
Not all types of nested classes should be used routinely, so you will likely encounter
most of them in other people�s code.
Should read
Not all types of nested classes should be used routinely, however, you will likely
encounter most of them in other people�s code.
{131} Example 7-1
Missing line of code. Add the line
private int beepCount = 1;
between the following two lines
public class InnerClassDemo extends JDialog {
public InnerClassDemo(final int beepCount) {
so that the code looks like:
public class InnerClassDemo extends JDialog {
private int beepCount = 1;
public InnerClassDemo(final int beepCount) {
(135) 2nd paragraph last sentence
Also, make sure that an abstract inner class doesn�t make the enclosing class
abstract, as with an abstract method.
should be
Also, note that an abstract inner class doesn�t make the enclosing class
abstract, as is the case with an abstract method.
<135> Example 6-3
Replace the line
package oreilly.hcj.nested;
With
package oreilly.hcj.nested2;
(To reflect a repackaging.)
[136] 2nd codesample;
System.out.println(resoultion);
should be
System.out.println(resolution);
{136} End of Second paragraph (paragraph right after the second code snippet)
Replace
Since ColorPixelPoint is not a member of BasicMonitorScreen, access to
BasicMonitorScreen�s private and protected members is not allowed.
With the text
Since ColorPixelPoint is not a member of BasicMonitorScreen, it doesn�t
gain any of the privileged access rights of a member nested class. For example,
ColorPixelPoint would not have access to BasicMonitorScreen�s private members.
(143) Last paragraph before Example 6-7
The text
Since the syntax of anonymous classes is not considered to be mainstream Java
syntax, anonymous classes are difficult to read and are often misunderstood.
Should read
Since the syntax of anonymous class declaration is so radically different from
the normal Java syntax, anonymous classes are difficult to read and are often misunderstood.
(147):
"...see the source code to java.util.HashTable"
should read
"...see the source code to java.util.Hashtable"
(151) Table 6-1;
Heading "Keywords" in the title of the table should start from abstract/final, not instance.
{161} Paragraph before the first code snippet
If you want to remove standard tires from your hypothetical car, you can use an
exclusive OR (XOR�the ^ operator) operator:
Should read
If you want to remove standard tires from your hypothetical car, you can use an
bit-wise AND operator in combination with the bit-wise NOT operator:
{161} First code snippet
myCar.setOptions(myCar.getOptions( ) ^ Car.STANDARD_TIRES);
should read
myCar.setOptions(myCar.getOptions( ) & ~Car.STANDARD_TIRES);
{161} First paragraph after the first code snippet
The paragraph
This piece of code removes the standard tires from the bit field. By applying an
XOR against the field, you clear the set bit However, realize that if the bit hadn�t
been set, you would have just set it. The only way to clear an entire bit, whether
the bit is set or not, is to create a bit field mask of all bits except for the one
you want to clear. After you create the mask, you must use a logical AND operator to
combine the mask and the target bit field:
Should read
This piece of code removes the standard tires from the bit field. By applying an AND
against the bit-wise NOT of the bit you intend to remove, you can clear the set bit
without disturbing the other bits in the bit field.
<161> Second code snippet and following paragraph
Remove both of these. The section should end after the paragaph in the previous entry.
{164} 3rd code snippet
public final static String LOCALE_US = 0;
public final static String LOCALE_UK = 1;
public final static String LOCALE_DE = 2;
should read
public final static int LOCALE_US = 0;
public final static int LOCALE_UK = 1;
public final static int LOCALE_DE = 2;
{164} 4th code snippet
public final static int LOCALE_US = "fred";
public final static int LOCALE_UK = "joe";
public final static int LOCALE_DE = "john";
Should be
public final static String LOCALE_US = "fred";
public final static String LOCALE_UK = "joe";
public final static String LOCALE_DE = "john";
(166) Last paragraph;
"Suupose you introduce the country of Uruguay and give it the value of 1 by accident."
should be
"Suppose you introduce the country of Uruguay and give it the value of 6 by accident."
<168> First paragraph after the heading Constant Objects
Before the last sentence in the paragraph that reads:
To understand how constant objects work, look at the constant object class in Example 7-8.
Add the following as a note:
The Constant Object paradigm is a further development of a concept known as the
�Typesafe Enum Pattern� introduced by Josh Bloch in his book Effective Java. For
those of you familiar with this pattern, The constant object paradigm expands on
it significantly by introducing re-use, serialization, lookup and much more.
{168} Example 7-8;
public final class NetAppException2 extends Exception {
Should be
public final class NetAppException2 extends ConstantObject {
(169) In Example 7-9, Comment for method getName()
@return The name of the exception.
Should read
@return The name of the country.
(170) First paragraph after the second code snippet
The word "you" should be removed so that
Since the new setter takes an object of type Country2, the user cannot pass you anything except a Country2 object.
Should read
Since the new setter takes an object of type Country2, the user cannot pass anything except a Country2 object.
(178) In the first code snippet,
package .utilities;
should read
package oreilly.hcj.constants;
[179] First example on page;
Example instantiates Country4 objects instead of Country6 objects.
(190):
On the first line, "commonalties" should read "commonalities"
(192):
"...the data model is fairy substantive"
should read
"...the data model is fairly substantive"
{197} In the last code example,
The line
new Float(interestRate), new Float(interestRate));
should read
new Float(oldInterestRate), new Float(interestRate));
{198} Code Example continued from page 197
the line
interestRate, interestRate);
Should read
oldInterestRate, interestRate);
(212):
"...and blue values are between 0 and 256"
should read
"...and blue values are between 0 and 255"
(213):
"Consider the UML diagram in Figure 8-6..."
should read
"Consider the entity-relationship diagram in Figure 8-6..."
{221}:
"The getMethods() call extracted each of the public members of the Person class"
should read
"The getMethods() call extracted each of the public methods of the Person class"
{226} First code snippet
the line
public void setValues(final String value, final int index) {
should read
public void setValue(final String value, final int index) {
and the line
public String getValues(final int index) {
should read
public String getValue(final int index) {
[246] First bullet point
Replace the text:
This restriction exists because if the proxy simply extended the implementation, a
user would be able to cast the proxy to the implementation and bypass the proxy
altogether. For example, if you create a proxy to implement a security policy and
the user can cast away the proxy, then you would have a huge hole in your security.
With the text
One of many reasons that this restriction exists is because the user of the proxy
class often doesn�t even have access to the implementation classes. For example, in
an EJB system the implementation class is on the server side and not even bundled
with the client. If the proxy class inherited from the implementation then you would
get ClassNotFound exceptions when trying to run the client.
<262> Figure 11-3
The arrow from Cache to Data Object is a different arrow than the one going from Data Object to Second Panel. Currently they are merged and should be separated.
(266):
"...or causes the class holding the reference variable to go out of scope"
should read
"...or causes the object holding the reference variable to go out of scope"
<266> Last paragraph on the page.
The paragraph
First, the virtual machine tries to trace a path from the root set to the object. If it
doesn't find a path, the virtual machine removes the referenced object from memory.
Next, the virtual machine determines whether there are reference objects pointing to
the removed reference, including weak, soft, and phantom references. If there are
reference objects, the virtual machine determines whether they are soft references.
If so, it does a memory check. If the memory check indicates that there is no free
memory or that the reference is a weak or phantom reference, the referent in the reference
is set to null. Finally, if the reference objects are registered with a queue, the
reference is added to the queue.
Should be replaced by the rewritten paragraphs indicated below
First, the virtual machine tries to trace a path through strong references from the root
set to the object. If it doesn�t find a path, the virtual machine checks to see if there
is a path through soft references. If there is no path through strong references as well,
then the virtual machine will garbage collect the object. On the other hand, if there is
a path through soft references, the virtual machine will check to see if it is low on heap
memory. If so, then it will garbage collect the object: otherwise the virtual machine will
skip that object and move on.
After the virtual machine has determined that an object should be garbage collected, its
next job is to determine whether there are weak, soft, or phantom reference objects pointing
to the garbage collected object. If it finds any, the referents in the located references are
set to null. Finally, if the located reference objects are registered with a ReferenceQueue,
the reference object will be added to that queue.
(271) Last sentence of the paragraph after the first code snippet
The text:
Essentially, concurrent modifications are the rule rather than the exception.
Should read:
However, just because the virtual machine will be making concurrent modifications to the
set doesn't mean that you are allowed to as well. If you try to manipulate the set yourself,
other than by using the methods provided in the Iterator class, while iterating it you will
still get a ConcurrentModificationException.
{278} Code snippet at bottom of page
package oreilly.hcj.tiger.
should read
package oreilly.hcj.tiger;
{279} Second code snippet
package oreilly.hcj.tiger.
should read
package oreilly.hcj.tiger;
(281) last code snippet
public void someMehtod(final Integer x) {
should read
public void someMethod(final Integer x) {
{289} Second and third Code snippets
package oreilly.hcj.tiger.
should read
package oreilly.hcj.tiger;
{290} Second Code snippet
package oreilly.hcj.tiger.
should read
package oreilly.hcj.tiger;
{291} First code snippet
package oreilly.hcj.tiger.
should read
package oreilly.hcj.tiger;
(291):
"Substitution continues until the all of the arguments are used"
should read
"Substitution continues until all the arguments are used"
{297} First code snippet
Pair<String, Integer> nvp = new Pair<Integer, String>( );
Should read
Pair<String, Integer> nvp = new Pair<String, Integer>( );
{308} Example 12-2
The method that starts with the following code
/** Third. */
public static <Type> Type someMethod(final Type obj, List<Type> list) {
is declared twice. Remove the first one.