Inhaltsverzeichnis

Errata

Trotz aller Sorgfalt beim Schreiben und beim Prüfen eines umfangreicheren Buchs ist es kaum möglich, kleine (und leider manchmal auch größere) Druckfehler oder sonstige Versehen völlig zu vermeiden. In manchen Fällen hat sich auch nur die Bedeutung einzelner Konstrukte in Groovy gegenüber der Version, die dem Buch zugrunde liegt, geändert. Schauen Sie gelegentlich einmal herein; besonders, wenn Ihnen einmal etwas sehr komisch im Text vorkommen sollte.

Und falls Sie selbst einen Fehler im Buch finden, der hier noch nicht aufgeführt ist: Helfen Sie uns und den anderen Lesern, indem Sie ihn auf der Buchseite des Verlags melden.

Zu Kapitel 1: Erste Schritte

Seite 8. Oberes Listing:
Statt System.properties.sort {…} muss es heißen: System.properties.entrySet().sort {…}. Die Elemente einer Hashtable sind nicht direkt sortierbar, man muss sie daher zunächst mit Hilfe der entrySet()-Methode in ein Set verwandeln, für das die Methode sort() definiert ist.

Zu Kapitel 2: Die Sprache Groovy

Seite 18. Kasten „Warum ist Groovy anders“, erster Punkt der Aufzählung in der Mitte der Seite:
Statt "abc".toUpperCase()=="abc" heißt es richtig "abc".toUpperCase()=="ABC".

Seite 28. Listing in der Mitte: Die Zeile

groovy> println zahlen.[0] * zahlen.get[1]

ist völlig missraten und sollte durch die folgende ersetzt werden:

groovy> println zahlen[0] * zahlen[1]

Seite 40. Unter Statisches this sollte das Listing folgendermaßen lauten:

class EineKlasse {
  static main (args) {
    assert this == EineKlasse
  }
}

Seite 41. Unter Generische Datentypen sind in new ArrayList<String>{} die geschweiften Klammern durch runde Klammern zu ersetzten: new ArrayList<String>().

Seite 41. Unter Annotationen fehlt der Hinweis, dass Array-Argumente zu Annotationen bei Groovy in eckigen Klammern stehen müssen und nicht in geschweiften Klammmern wie bei Java.

Seite 42. Unter Das typsichere Enum sollte erwähnt werden, dass, wenn ein Enum als switch-Wert verwendet wird, die case-Werte unter Groovy vollständig referenziert werden müssen. Angenommen, Sie haben folgenden Enum-Typ definiert:

enum E { ALPHA, BETA, GAMMA }

Wenn die variable e einen E-Wert hält, genügt es unter Java, als case-Wert den Elementnamen anzugeben:

switch (e) {
  case ALPHA: ...
}

Bei Groovy ist dagegen Folgendes nötig:

switch (e) {
  case E.ALPHA: ...
}

Alternativ können Sie auch den Enum-Typ einfach statisch importieren:

import static E.*

Zu Kapitel 3: Objekte in Groovy

Seite 50. Im Listing Beispiel 3-2 sollte die erste Zeile ganz am Ende stehen, um zu zeigen, dass in einem Groovy-Skript die import-Anweisung irgendwo im Programm (außerhalb einer Klassen- oder Methodendefinition) stehen kann.

Seite 52. Decompiler-Listing oben:
In der drittletzten Zeile müssen das public und ein geschweiftes Klammerpaar entfernt werden. Die Zeile sieht dann so aus:

static {...}

Seite 64. Oberes Listing:
Es fehlt die folgende zweite Zeile:

Calendar calendar = new GregorianCalendar()

Seite 72. Groovy-Listing in der Mitte:
Hier sollte in der vorletzten Zeile enabled:true stehen, damit es mit dem Java-Code oberhalb übereinstimmt.

Seite 74/75. Tabelle 3-1 Operatoren und Operatormethoden, Abschnitt Arithmetische Operatoren:
Die Negation wird jetzt in einen eine Aufruf der Methode unaryMinus() übersetzt.
Der zum Modulo-Operator gehörende Ausdruck lautet nicht x / y sondern x % y.
Abschnitt Binäre Operatoren:
Das Komplement wird jetzt in einen Aufruf der Methode bitwiseNegate() übersetzt.
Abschnitt Sonstige Operatoren:
Der Methodenaufruf zu x in y lautet x.isCase(y).

Generell fehlt hier der Hinweis, dass die Operator-Aufrufe bei JDK- und Groovy-Standardklassen aus Performance-Gründen teilweise bereits durch die Groovy-Laufzeitumgebung implementiert werden.

Seite 76. Listing Beispiel 3-3:
Folgende Zeile (etwa in der Mitte der Seite)

normalwert = arg.normalwert * faktor

ist folgendermaßen zu ändern:

wert = arg.normalwert * faktor

Seite 79. Abschnitt Dereferenzieren von Listen:
Die folgende Anweisung

groovy> println bookmarks.getProtocol()

funktioniert in der aktuellen Groovy-Version nicht mehr in dieser Form (wobei nicht ganz klar ist, ob es dies absichtlich so ist). Um sicher zu gehen, sollte man immer den Spread-Dot-Operator (*.) verwenden, um Methoden oder Properties bei allen Elementen einer Liste aufzurufen.

groovy> println bookmarks*.getProtocol()
groovy> println bookmarks*.protocol.unique()

Zu Kapitel 4: Neue Konzepte

Seite 92. Am Ende des vorletzten Absatzes der Seite muss es heißen: “…und sich als Comparator verkleidet.“

Seite 94/95. In dem Skript, das unten auf Seite 94 beginnt, sollte nach println this.class noch eine Zeile println owner.class folgen. Diese Anweisung führt dazu, dass ein zweites Mal class TestClosure1 ausgegeben wird.

Seite 96. Beispiel 4-3: Die drei Protokollausgaben beginnen jeweils mit log(…) (klein geschreibenes l).

Wie ein Leser anmerkt, ist das Beispiel in der abgedruckten Form nicht besonders instruktiv, da man den gleichen Effekt auch mit einer normalen log()-Methoden hätte. Sinnvollerweise sollte die Closure zur Auführung des Logging von außen gesetzt werden.

Seite 98. Letzer Absatz, zweiter Satz: Richtig muss es heißen: „Indem wir es an die print()-Methode einer Instanz des groovy.util.NodePrinter übergeben…“.

Seite 99. Zweiter Absatz, letzter Satz: Richtig muss es heißen: „Sie können nicht einfach it.bez schreiben…“.

Seite 99. Tabelle 4-1: In den drei letzten Zeilen der Tabelle ist unter „Beispiel“ art durch n zu ersetzen.

Zu Kapitel 5: Wie Groovy das JDK erweitert

Seite 119. Tabelle 5-2: In der fünften Zeile muss das letzte Beispiel-Literal 1e2f lauten. Der Wert 1e2 bezeichnet dagegen - anders als in der darauffolgenden Tabellenzeile angegeben - einen BigDecimal-Wert, und zwar unabhängig davon, ob Sie ein 'G'/'g' dranhängen oder nicht.

Seite 127. Im Beispiel oben auf der Seite sollte die erste Zeile lauten:

groovy> text = new StringBuffer("YOGAVORGIRLS")

Im letzten Textabsatz sollte der Satz „Das gilt auch für Strings, die in Schrägstrichen eingeschlossen werden“ so ergänzt werden: “…, sofern es wie der Beginn eines GString-Platzhalters aussieht.“

Seite 144. Im Beispiel ganz unten muss es „Beispiel.txt“ statt „Pangramm.txt“ heißen.

Seite 169. Der body-Abschnitt im Beispiel oben auf der Seite sollte korrekt so aussehen:

body {
    h1 "Die Hello-World-Seite"
    p "Die aktuelle Zeit ist: ${new Date()}"
}

Die darunter wiedergegebene HTML-Version ändert sich dann sinngemäß.

Außerdem muss in dem Satz, der dem ersten Beispiel folgt, „Reader“ durch „Writer“ ersetzt werden.

Zu Kapitel 7: Dynamisches Programmieren

Seite 185. Das Beispiel oben auf der Seite soll zeigen, wie eine in einer Kategorienklasse definierte Methode eine klassenspezifische Methode überschreibt. Es funktioniert nicht mehr in dieser Form; auch wenn die DumpKategorie aktiv ist, wird nun in jedem Fall die Methode dump() von AndereKlasse aufgerufen.

In der Groovy-Version 1.5 haben offenbar spezifische Methoden auch Vorrang vor Methoden, die in Kategorienklassen definiert sind. Damit entfällt die mögliche Gefahrenquelle, auf die in der Warnung im unteren Teil derselben Seite hingewiesen wird.

Seite 197. Im ersten Beispiel oben fehlt ein $-Zeichen in der zweiten Zeile. Es muss also zweimal lauten: ${resultSet…}.

Das zweite Beispiel sollte komplett so lauten:

kapsel = new ResultSetWrapper(resultSet)
while (resultSet.next()) {
    println "$kapsel.vorname $kapsel.zuname"
}

Seite 210. Listing Beispiel 7-4:
Die erste Zeile muss jetzt folgendermaßen lauten:

emc = new ExpandoMetaClass(String,true)

Ohne den zweiten, auf true gesetzten Parameter wird die Metaklasse nicht registriert und bleibt damit wirkungslos.

Seite 210/211. Der Satz „Insofern ist die ExpandoMetaClass etwas weniger gefährlich als die Kategorienklassen,…“ gilt nicht mehr, wie oben zu Seite 185 erläutert.

Zu Kapitel 8: Groovy und Java integrieren

Seite 218. In der Testklasse ganz unten auf der Seite lautet die Zeile 6 korrekt so:

Map properties = dyn.invoke(Map.class,"getProperties");

Alternativ kann man auch das erste Argument mit der Klasse weglassen, dann liefert die Methode aber eine Object-Instanz, die entsprechend gecastet werden muss.

Seite 219. Im Testskript ganz oben auf der Seite lautet die Zeile 5 korrekt so:

String textVerkehrt = dynText.invoke(String.class,"reverse")

In der Erweiterung der DynamicObject-Klasse darunter sollte die Typisierung an dieser Stelle entfallen. Die iterator()-Methode sieht dann so aus:

public Iterator iterator() {
    return invoke(Iterator.class,"iterator")
}

Der letzte Zeile des Beispiels für den Aufruf der Methode lautet dann so:

for (Object c : new DynamicObject(s)) { . . . }

Seite 229. Abschnitt Privilegierte Aktionen: Im Beispiel oben soll der Name der Methode getUserName() lauten.

Zu Kapitel 9: Groovy im Entwicklungsprozess

Seite 237. Beispiel 9-1: Hier sind in zwei <target>-Tags die depends-Attribute verwechselt worden. Statt

<target name="runjava" depends="buildjava">
...
<target name="rungroovy" depends="buildall">

muss es richtig heißen:

<target name="runjava" depends="buildall">
...
<target name="rungroovy" depends="buildjava">

Seite 239. Beispiel 9-2: In der letzten Zeile der Methode buildall() sind die Kommentarzeichen zu entfernen.

Und die letzte Zeile der Methode runjava() sollte "GroovyKlasse" durch MAINCLASS ersetzt werden.

In der Methode dist() schließlich wird nicht build(), sondern buildall() aufgerufen.


Vielen Dank an alle Leser, die durch ihre Aufmerksamkeit helfen, Fehler, Lücken und Unklarheiten im Buch zu beseitigen.