If you spot a problem in the first edition that is not listed here, please open an issue. I do not accept pull requests on this repo, but I acknowledge reporters on the main page.
- Page 1: "...the only thing left it to put the poem together..." should be "...the only thing left is to put the poem together..."
-
Page 15: "a two-element array of type
int
, which supports(2^33)+1
values". This should read "...(2^64)+1
values" (which makes the argument that much more compelling!). -
Page 23: The comment
/* Suffle the cards */
should read/* Shuffle the cards */
. -
Page 33: In the constructor for
Card
at the bottom of the page, the Boolean conditions are negated. They should readpRank == null
andpSuit == null
. -
Page 36: The paragraph "
Card
in Solitaire" refers to the enumerated types as inner types. In fact these had been moved to top level types for versionv1.0
. To see them as inner types, check out versionv0.4
.
- Page 52: In the code samples here and elsewhere, an
Iterable
class that aggregates aList
implements methoditerator()
by delegating the call to its aggregate:return aCards.iterator()
. Strictly speaking, this idiom can violate the encapsulation of classDeck
because interfaceIterator
includes a methodremove
that can be optionally implemented (and which is implemented byArrayList
). Consistent with the book's goal of focusing on general design concerns with minimum coverage of the libraries, I overlook this case. In the context of the book it can be assumed thatIterator.remove()
is not used. For production code how to best avoid the encapsulation problem would depend on the properties of the context. One option is to return the iterator obtained from an unmodifiable view of the list, e.g.,return Collections.unmodifiableList(aCards).iterator()
.
-
Page 63: 'A more useful abstract state for Player would be "non-zero score" and one for Deck would be "empty", which in both cases happen to correspond to a single concrete state.' The second clause only applies to the "empty" state. Although "zero score" maps to a single concrete state for an integer, obviously, non-zero scope maps to
2^32-1
concrete states (if the full integer range is permitted). -
Page 74: Field
NULL
of interfaceCardSource
does not require thepublic
modifier as interface fields are implicitlypublic
andfinal
. -
Page 86: In the code fragment at the top of the page, the use of the parameter
pRank
is superfluous incountCards
because this instance method of the anonymous class can refer to the implicit fieldpRank
directly. The better version is here.
Nothing to report.
- Page 126: The definition of
CompositeCardSource
is missing the declarationimplements CardSource
, see the correct version. - Page 143: The definition of class
CompositeCardSource
declares fieldaSources
asfinal
, but this is not possible due to the requirement to implement methodclone()
. To make the code work, it is necessary to remove thefinal
keyword. - Page 147: The definition of class
Deck
is missing the return type in the declaration ofcreateDrawCommand()
and the semicolon at the end of the statement. SeeDeck
for the corrected version.
- Page 161: "The fact that the code in class
MemorizingDeck
cannot access (or see) the field declared in its superclass does not change anything about the fact that this field is inherited". Surprisingly, the Java Language Specification (JLS) considers that private fields are not inherited. This is a matter of terminology, because objects of subclasses do include the private fields declared in their parent classes. In the context of teaching object-oriented design, mixing visibility and inheritance is very confusing, so I do not retain the terminology of the JLS. In the book, the concepts of field inheritance and visibility are kept consistently distinct. - Page 161: In the code example,
pulic
should bepublic
. - Page 162: "the first instruction of any constructor is to call a constructor of its superclass" is not completely accurate because it is also possible to call a constructor of the same class with
this(...)
. - Page 162: In the first code fragment,
Cards.get
should beCard.get
andSuit.SPACES
should beSuit.SPADES
. - Page 162: In Figure 7.5,
MemorizingDeck
should have field namedaDrawnCards
notaCards
. - Page 176: class
AbstractDecorator
is intended to be also declared asabstract
. SeeAbstractDecorator
for the corrected version. - Page 185: For the first code fragment to work as expected, the first line should read
MemorizingDeck deck = new MemorizingDeck();
- Page 200: "(ISP, see Section 3.2)" should be (ISP, see Section 3.8);
- Page 203: In the declaration of interfaces
ChangeObserver
andBoundsReachedObserver
, the empty method declarations ({}
) should be replaced with a semicolon.
- Page 238: method
compareByRank
would be best declaredpublic
so it can be usable outside the class. - Page 249: there are two extra parentheses in the first sorting code fragment. See the corrected version as method
sampleSortingApplication1
in Card.java. - Page 255: in the second code fragment,
comparator.comparing..
. should beComparator.comparing...
. - Page 255: the sequence diagram shows two function objects as key extractors (
f1
andf2
). However, there is only a single key extractor object involved in this scenario.
Unless otherwise noted, the content of this repository is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
Copyright Martin P. Robillard 2019-2022