Fast alle der hier aufgezählten Fehler sind in den aktuellen Nachdrucken des Buchs bereits behoben.
Die Beispieldateien zur 1. Auflage finden Sie hier: https://www.rheinwerk-verlag.de/java_3632/
Bitte beachten Sie, dass es von diesem Buch eine aktuellere Auflage gibt!
Seite 69, Casting
Bei einer Überschreitung des Zahlenbereichs bei einem erzwungenen Casting kommt es zu keiner Exception. Vielmehr enthält die Variable i
im folgenden Beispiel eine total falsche Zahl.
long l = l = 17_000_000_000L;;
int i = (int)l; // Vorsicht: wenn der Wert in l den den
// int-Zahlenbereich überschreitet, enthält
// i einen vollkommen falschen Wert
System.out.println(i) // Ausgabe: -179869184
Seite 72, Fließkommazahlen
Im Absatz nach der Überschrift: 1.23e4 bzw. 1.23E4 1.23e3 bzw. 1.23E3 bedeutet 1,23 x 10^3. (Die nachfolgenden Code-Beispiele sind richtig.)
Seite 75 mitte, Objektvariablen
Natürlich müssen auch Objektvariablen zuerst initialisiert werden, bevor Sie ausgelesen werden können. Nur innerhalb von Klassen werden Instanzvariablen mit 0, 0.0, false bzw. null automatisch initialisiert. Gleiches gilt für die Elemente eines Arrays.
Seite 77, clone
in der zweiten Zeile des Listings muss es lautet: p3.clone()
, nicht p1.clone()
:
Point p3 = new Point(3, 3);
Point p4 = (Point)p3.clone();
p4.x = 4;
System.out.println(p3.x + " " + p4.x);
// Ausgabe: 3 4
Seite 82, Beispiel zu java.util.Scanner
Im Listing auf der Seitenmitte habe ich laenge
und breite
durcheinander gebracht. Richtig muss der Code so aussehen:
double laenge = Double.parseDouble(eingabeLaenge);
double breite = Double.parseDouble(eingabeBreite);
Seite 95, Rechnen mit Bits
0b11100
ist 28, nicht 26.
int a = 0b11100; // 28 = 0b11100
Seite 185 bis 186, Lotto-Beispiel
Es ist mir wirklich peinlich (mea culpa!): Das Lotto-Beispiel enthält gleich drei Fehler:
- In der Methode
gewinnzahlen
muss die Bedingung für diefor
-Schleifei<n
lauten, nichti<n-1
. - Ebenfalls in dieser Methode sollte sich die
continue
-Anweisung auf die äußeredo
-Schleife beziehen. Deswegen muss vor derdo
-Schleife ein Label gesetzt werden, anstelle voncontinue
heisst es danncontinue label
. - Schließlich muss die
while
-Bedingung inmain
mitfalse
formuliert werden, sonst ist der erste Tipp sofort ein Treffer. Das wäre zu schön, um wahr zu sein.
public static int[] gewinnzahlen() {
int[] ziehung = new int[6];
int zahl;
Random r = new Random();
int n=0;
// Schleife für alle sechs Zahlen
do_label: // <-- Korrektur
do {
zahl = 1 + r.nextInt(49);
// testen, ob Doppelgänger
for(int i=0; i<n; i++) {
if(ziehung[i] == zahl)
continue do_label; // <-- Korrektur
}
ziehung[n]=zahl;
n++;
} while(n<6);
Arrays.sort(ziehung);
return ziehung;
}
...
// in main: Schleife; so oft Lotto spielen,
// bis die sechs Zahlen übereinstimmen
do {
n++;
ziehung = gewinnzahlen();
} while(Array.equals(tipp, ziehung) == false); // <---
Das korrigierte Beispiel können Sie hier herunterladen:
Seite 194, try-catch für Ressourcen
Die Ressourcen innerhalb von try(...)
müssen durch Semikola getrennt werden, nicht durch Kommas. Also:
try(IOKlasse1 x = new IOKlasse1("dateiname1");
IOKlasse2 y = new IOKlasse2("dateiname2")) { ...
Seite 208, Box zu Top-Level-Klassen
Der Text in der Box ist falsch und widerspricht der korrekten Tabelle von der Vorseite: Somit gilt für Top-Level-Klassen ohne protected
, private
oder public
ein Mittelding zwischen protected
und private
. Die Klasse ist nur im Paket zugänglich, nicht aber in abgeleiteten Klassen oder gar außerhalb!
Seite 235, Methoden überschreiben
Beim Überschreiben von Methoden ist es nicht erforderlich, dass die Sichtbarkeit gleich bleibt — sie darf nur nicht eingeschränkt werden. Eine public-Methode kann also nicht durch eine private-Methode überschrieben werden. Umgekehrt ist es aber z.B. zulässig, dass eine protected-Methode durch eine public-Methode überschrieben wird.
Auch der Rückgabewert muss nicht zwingend identisch sein. Dies gilt nur für Werttypen. Bei Referenz-Typen kann die überschreibende Methode auch einen Subtypen zurückgeben. Beispiel: Methode m der Klasse K1 liefert eine Instanz von Typ A zurück. Methode m der Klasse K2 extends K1
darf eine Instanz von Typ B zurückgeben, wenn B von A abgeleitet ist (also A extends B
oder A implements B
, natürlich auch bei Vererbung/Schnittstellen über mehrere Schritte).
Seite 241, Generalisierung
Im Beispiel-Code auf S. 241 mitte fehlt der Casting-Operator (C1)
, damit der Compiler weiß, dass er obj3
als Objekt der Klasse C1
betrachten soll:
obj3.x1(); obj4.x2(); // nicht erlaubt
C1 obj5 = (C1)obj3; obj5.x1(); // OK
^^^^
((C2)obj4).x2(); // auch OK
Seite 241, Polymorphie
Die Regeln der Polymorphie gelten nur für überschriebene Methoden. Soweit Felder sichtbar sind, wird immer auf das Feld der Basisklasse zugegriffen, nicht auf ein eventuell gleichnamiges Feld der abgeleiteten Klasse.
Seite 243, Polymorphie
Im Code-Beispiel in der Seitenmitte muss es in der vierten Zeile a.anzahlSitze()
anstelle von f.anzahlSitze()
heißen. Das ganze Listing sieht damit so aus:
void m(Fahrzeug f) {
if(f instanceof Auto) {
Auto a = (Auto)f;
int sitze = a.anzahlSitze();
} else if (f instanceof Fahrrad) {
Fahrrad fr = (Fahrrad)f;
boolean federgabel = fr.hatFedergabel();
}
...
}
Seite 257, implements
Mit implements
verpflichten Sie sich normalerweise, alle Methoden einer Schnittstelle zu implementieren. Wenn es sich bei Ihrer Klasse um eine abstrakte Klasse handelt, können Sie diese Verpflichtung aber auch weitergeben, indem Sie die betreffende Methode abstrakt deklarieren. Die tatsächliche Implementierung erfolgt dann in der Klasse, die später von Ihrer Klasse abgeleitet wird.
Seite 271, Upper Bounded Wildcards
<? extends Xxx>
gilt nicht nur für von Xxx abgeleitete Klassen, sondern auch für Xxx selbst.
Seite 272, Upper Bounded Wildcards
In der Mitte des Listings sollte statt outputTriplet
natürlich sumTriplet
stehen, also:
Double result = sumTriplet(t2);
Seite 290, Tabelle »Die wichtigsten Lambda-Schnittstellen«
In der vierten Zeile der Tabelle muss es nicht Consumer<T, U>
heißen, sondern BiConsumer<T, U>
.
Seite 291, Listing Predicate-Schnittstelle
Im Listing am Beginn der Seite ist das Wort ‚More‘ enthalten, dass dort nichts verloren hat. Das Listing sieht korrekt so aus:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
... sowie diverse Defaultmethoden
}
Seite 309, descendingIterator-Methode
Im Listing auf S. 309 unten wird die Methode decendingIterator
gezeigt, um eine Schleife in umgekehrter Reihenfolge zu durchlaufen. Diese Methode steht allerdings nicht allgemein für Sets, sondern nur für TreeSets zur Verfügung. Sie kann daher nur nach einem Cast in diesen Typ angewendet werden. Das Listing sieht korrekt so aus:
// Schleife in umgekehrter Reihenfolge
TreeSet<Point> ts = (TreeSet) set;
for(Iterator<Point> pit = ts.descendingIterator();
pit.hasNext(); ) {
Point p = pit.next();
System.out.println(p.x + " " + p.y);
}
Seite 333, Files.walk-Methode
Das Beispielprogramm kap15-io-intro führt bei der Ausführung unter Windows zu einer Exception. Diese wird durch Files.walk(...)
verursacht, sobald die Methode auf eine Datei oder ein Verzeichnis stösst, das aufgrund fehlender Zugriffsrechte nicht gelesen werden kann. Aufgrund der internen Implementierung dieser Methode lässt sich die Exception nicht wie bei anderen Methoden durch try/catch
abfangen. Hintergründe zum Problem können Sie hier nachlesen:
http://stackoverflow.com/questions/22867286
https://bugs.openjdk.java.net/browse/JDK-8039910
Eine mögliche Alternative besteht darin, anstelle von Files.walk
die Methode Files.walkFileTree
zu verwenden (Details siehe hier und hier). Diese Methode bietet mehr Flexibilität bei der Fehlerabsicherung, ist aber deutlich komplexer in ihrer Anwendung und als Beispiel für ein Java-Einführungsbuch ungeeignet.
In zukünftigen Auflagen meines Java-Buchs werde ich auf die Erwähnung von walk
verzichten. Die walk
-Methode ist nur auf den ersten Blick einfach zu nutzen; in ihrer aktuellen Form ist sie in der Praxis für die meisten Anwendungen ungeeignet.
Seite 335, Listing Seitenmitte
Anstelle von Files.createDirectory(v23)
muss es Files.createDirectories(v23)
lauten, weil ein Verzeichnis und ein darin enthaltenes Unterverzeichnis erzeugt werden. (In den Beispieldateien ist der Code korrekt.)
Seite 336, Ergebnisse des Beispiels kap15-io-change
Das Programm erzeugt die folgenden Verzeichnisse und Dateien:
verz1/
datei1.tmp
datei2.tmp (nicht datei1.tmp wie im Buch angegeben)
verz2/
uv3-neu/
Seite 397, Lösung zu Aufgabe W2 aus Kapitel 3 (Postfix/Präfix-Notation)
Ich habe Post- und Präfix durcheinander gebracht. Die Lösung d=-25 ist zwar korrekt, aber die Erklärung ist falsch. Richtig muss die Erklärung so lauten:
Java verarbeitet die Zuweisung an d
so:
d = (a--) - (b--) - c;
Da --
hier in der Postix-Notation angewendet wird, berücksichtigt Java die
ursprünglichen Inhalte von a
und b
, also:
d = 7 - 12 - 20;
Nach der Berechnung des Werts für d
werden auch die Variablen a
und b
geändert. Somit ergibt sich: a=6
, b=11
, c=20
und d=-25
.
Letzte Änderung am 28.11.2018. Vielen Dank an alle Leser und Leserinnen für das Feedback!
Seite 86, Wiederholungsaufgabe 5: Es steht bereits die Lösung in der Aufgabenstellung.
Es müsste eigentlich in der Aufgabenstellung heissen:
…
s = s + i;
…
danke für die beiden Hinweise, Sie haben natürlich recht
Seite 77, Beispielcode
korrekt wäre:
…
Point p4 = (Point)p3.clone(); //und nicht (Point)p1.clone!
…
ansonsten macht das Beispiel keinen Sinn.
Bitte prüfen Sie nochmals folgendes..
Seite 235: Methoden überschreiben
– Name und Parameterliste exakt gleich. (ok)
– Sichtbarkeit nicht eingeschränkt
– Rückgabenwert gleich (primitive Datentypen) oder Subtyp (bei Referenzen)
Seite 241: Polymorphie:
– Zur Laufzeit wird die überschriebene Methode des Objekts verwendet. (ok)
– Falls sichtbar, dann ist es ein Feld des Referenztyps ( nicht des Objektes) auf das zugegriffen werden kann
Seite 257: Die implements Syntax
Es ist auch möglich eine Methode und damit auch die Klasse abstract zu deklarieren.
Insofern ist implements keine Verpflichtung die Methoden zu implementieren
Bitte um Feedback falls ich mich irren sollte.
Danke!
vielen Dank für die Hinweise, ich habe die Errata um entsprechende Klarstellungen ergänzt
Seite 107: Absatz nach dem Beispiel
Hier wird explizit darauf hingewiesen, dass im „obigen“ Beispiel auf die geschwungenen Klammern verzichtet worden ist. Im Beispiel sind aber die angesprochenen Klammern jedoch vorhanden.
Sie haben recht. Damit das Beispiel zum Text passt, sollte es so aussehen:
In Kapitel 11.1 Vererbung Seite 243 wird im Programmbeispiel die Methode f.anzahlSitze() aufgerufen. Sollte an dieser Stelle nicht a.anzahlSitze() aufgerufen werden, da sie ja für die Basisklasse nicht verfügbar sein sollte?
Falls ich mich irren sollte bitte ich Sie um Rückmeldung, da ich zum ersten Mal durch Ihr Buch mit OO-Programmierung in Berührung gekommen bin.
Danke!
doch. Ich habe die Errata entsprechend erweitert, danke für den Hinweis.
Erratum eines Erratums (Seite 185 bis 186, Lotto-Beispiel): „Deswegen muss for der do-Schleife …“.
ist korrigiert :-)
In Kapitel 4, 4.4 For Schleifen habe ich noch einen Fehler gefunden. Auf Seite 107 unter dem Code-Beispiel der kurzen For-Schleife steht im Text, dass auf die geschwungenen Klammern verzichtet wird, da die Anweisung nur aus einer Zeile besteht. Das Code-Beispiel enthält aber die geschwungenen Klammern.
mfg
Seite 69 oben: Es wird fälschlicherweise behauptet, dass beim Integer-Casting ein Überlauf zu einer Exception führt.
Danke, ich habe die Errata entsprechend ergänzt.
In der Tabelle der wichtigen funktionalen Schnittstellen auf Seite 290 erscheint die Schnittstelle Consumer zweimal, einmal mit einem und einmal mit zwei Typ-Parametern. Das scheint mir nicht korrekt. Sollte die Schnittstelle mit zwei Parametern nicht BiConsumer heißen?
Danke, ich habe die Errata entsprechend aktualisiert.
Es wäre recht hilfreich, wenn aus der mittlerweile einigermaßen langen Liste hervorginge, für welchen Nachdruck welche Errata noch gelten. Der vorangestellte Satz „Alle hier aufgezählten …“ ist offensichtlich nicht mehr zutreffend, und selbst wenn er es wäre, würde das Besitzern des ersten und zweiten Nachdrucks wenig nützen.
Vorschlag zu einer einfachen Lösung: Zu jedem Erratum könnte, sofern zutreffend, vermerkt werden: „korrigiert im soundsovielten Nachdruck.“
… oder man sortiert – mit entsprechenden Überschriften – zuerst nach Ausgabe/Druck und erst innerhalb dieser Gruppen nach Seitenzahlen.
Ich werde es bei der nächsten Auflage so handhaben.
In dem Beispiel-Listing für Upper Bounded Wildcards auf S. 272 wird eine Methode sumTriplets() zur Berechnung der Summe eines Triplets definiert, die dann aber nirgendwo aufgerufen wird. Stattdessen wird in der darüberliegenden Zeile eine Methode outputTriplet() aufgerufen, die bereits in einem früheren Listing vorkam:
Double result = outputTriplet(t2);
Meines Erachtens sollte in dieser Zeile eigentlich die Methode sumTriplets() stehen, also:
Double result = sumTriplet(t2);
Sie haben Recht, danke für den Hinweis.
In dem Beispiel für die Datenselektion mit der Schnittstelle Predicate auf S. 291 steht in der Definition der funktionellen Schnittstelle Predicate in der Signatur der Methode test zwischen dem Rückgabewert boolean und dem Methodennamen test das Wort „More“, das für mich an dieser Stelle syntaktisch keinen Sinn ergibt und – so meine Vermutung – nicht dorthin gehört:
public interface Predicate {
boolean More test(T t);
…
}
In der Java-Dokumentation von Oracle ist die Methode einfach folgendermaßen definiert:
boolean test(T t)
Danke für den Hinweis, ich habe die Korrektur in den Errata vermerkt.
Am Ende von S. 309 zeigt ein Listing, wie die Elemente eines TreeSets in absteigender Reihenfolge ausgegeben werden können:
Der Aufruf der Methode descendingIterator() für das Objekt set ist aber an dieser Stelle gar nicht möglich, weil set zuvor nicht als TreeSet sondern als Set deklariert wurde:
Eclipse schlägt daher an der Stelle, an der descendingIterator aufgerufen wird, einen expliziten Cast auf TreeSet vor:
danke, ist jetzt in den Errata vermerkt
Guten Tag
Auf S. 241 (1. Aufl.) bzw. auf S. 247 (2. Aufl.) wird Generalisation besprochen mit einem Beispiel von class A Objekten und abgeleiteten Klassen B, C1 und C2.
Die Zuweisung an Obj5 vom Typ C1 funktioniert nicht, ich habe das Problem auch auf Stackoverflow besprochen.
https://stackoverflow.com/questions/53514983/java-sdk10-is-cast-explicitly-required
Vielen Dank
Sie haben recht. In der 2. Zeile des fraglichen Listings fehlt ein Casting-Operator
(C1)
. Ich habe es auf den Errata-Seiten beider Auflagen des Buchs vermerkt. Vielen Dank für den Hinweis!Auf S. 350 wird die Methode setOnAction für die Checkbox verwendet, diese ist jedoch in dem Paket das die Checkbox zur Verfügung stellt, nämlich java.awt, nicht enthalten. Da hat sich wohl was verändert seit 2014. Welche alternative Methode sollte nun stattdessen verwendet werden?
Danke im Voraus für den Tip.
Der ganze Abschnitt bezieht sich nicht auf awt, sondern auf JavaFX.