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)+1values". This should read "...(2^64)+1values" (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
Cardat the bottom of the page, the Boolean conditions are negated. They should readpRank == nullandpSuit == null. -
Page 36: The paragraph "
Cardin 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
Iterableclass that aggregates aListimplements methoditerator()by delegating the call to its aggregate:return aCards.iterator(). Strictly speaking, this idiom can violate the encapsulation of classDeckbecause interfaceIteratorincludes a methodremovethat 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-1concrete states (if the full integer range is permitted). -
Page 74: Field
NULLof interfaceCardSourcedoes not require thepublicmodifier as interface fields are implicitlypublicandfinal. -
Page 86: In the code fragment at the top of the page, the use of the parameter
pRankis superfluous incountCardsbecause this instance method of the anonymous class can refer to the implicit fieldpRankdirectly. The better version is here.
Nothing to report.
- Page 126: The definition of
CompositeCardSourceis missing the declarationimplements CardSource, see the correct version. - Page 143: The definition of class
CompositeCardSourcedeclares fieldaSourcesasfinal, but this is not possible due to the requirement to implement methodclone(). To make the code work, it is necessary to remove thefinalkeyword. - Page 147: The definition of class
Deckis missing the return type in the declaration ofcreateDrawCommand()and the semicolon at the end of the statement. SeeDeckfor the corrected version.
- Page 161: "The fact that the code in class
MemorizingDeckcannot 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,
pulicshould 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.getshould beCard.getandSuit.SPACESshould beSuit.SPADES. - Page 162: In Figure 7.5,
MemorizingDeckshould have field namedaDrawnCardsnotaCards. - Page 176: class
AbstractDecoratoris intended to be also declared asabstract. SeeAbstractDecoratorfor 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
ChangeObserverandBoundsReachedObserver, the empty method declarations ({}) should be replaced with a semicolon.
- Page 238: method
compareByRankwould be best declaredpublicso 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
sampleSortingApplication1in 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 (
f1andf2). 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
