Groovy (http://groovy.codehaus.org/) ist eine objektorientierte Skriptsprache, die auf einer JVM läuft und vollen Zugriff auf alle Java-Bibliotheken bietet. Die Sprache hat viele interessante Eigenschaften, die sie zu Java X machen. Groovy setzt auf der Standard-Java-Syntax auf und erweitert diese.[1] Einige Höhepunkte:
Groovy-Feature | Beispiel |
Statt System.out.print(…)/println(…) reicht ein print bzw. println, und dann muss das Argument auch nicht in runden Klammern stehen. | println 1 + 2 print „Wow“ |
Anweisungen müssen nicht immer mit einem Semikolon abgeschlossen werden, sondern nur dann, wenn mehrere Anweisungen in einer Zeile stehen. | print „Wow“ print „Wow“; print „Wow“ |
Variablen müssen nicht mit einem Typ deklariert werden, das gilt auch bei catch oder Methoden/Konstruktoren. | def age = 40 def greet( name ) { print „Hallo “ + name } try { } catch ( e ) { } |
Zeichenketten lassen sich mit einfachen oder doppelten Anführungszeichen angeben. Einzelne Zeichen (char/Character) müssen besonders aufgebaut werden. | print „Ja“ == ‚Ja‘ // true def sign = „-“ as char |
Strings in doppelten Anführungszeichen sind besondere GStrings: Enthalten sie $variable bzw. ${ausdruck}, so wird der Inhalt der Variablen bzw. der ausgewertete Ausdruck eingesetzt. | def one = 1 print „$one plus $one macht ${1+1}“ // 1 plus 1 macht 2 |
Strings können über mehrere Zeilen laufen, wenn sie in „““ oder “‘ eingeschlossen sind – folgt ein Backslash am Ende der Zeile, wird kein Zeilenumbruchzeichen eingefügt. | print „““ Zeile 1 Zeile 2\ Weiter mit Zeile 2 „““ |
Alles ungleich 0 und null ist true. | if ( 1 ) print ‚Zweig wird genommen‘ |
Groovy definiert einen neuen Datentyp für Bereiche (engl. ranges). | def numbers1 = 0..9 def numbers2 = 0..<10 |
Erweiterte Zählschleife unter Berücksichtigung von Bereichen, bzw. rechts von in steht ein Iterable wie beim erweiterten for. | for ( i in 0..<10 ) print i // 0123456789 |
== bei Referenzen bedeutet equals(…)-gleich; ein Identitätsvergleich realisiert is(…). | def heinz = ‚Heinz‘ print heinz == ‚Heinz‘ // true |
Operatoren können überladen werden, und die Anwendung von Operatoren entspricht Methodenaufrufen, etwa + von plus(…), ++ von next(…) oder [] von getAt(…). | println 1 + 2 * 3 // 7 println 1.plus(2).multiply(3) // 9 println 1.plus(2.multiply(3)) // 7 |
Alle Comparable-Objekte (und damit etwa String, BigInteger, BigDecimal) können mit ==, !=, <, >, <= und >= verglichen werden. Die Ordnung liefert compareTo(…). | def heinz = ‚Heinz‘ print heinz < ‚Werner‘ // true |
Ist in Java nur java.lang standardmäßig importiert, ist es bei Groovy viel mehr, etwa noch java.io, java.util, java.net und noch einige. | print new File(‚file.txt‘).exists() |
Statt explizit auf Datenstrukturklassen für Listen und Mengen zurückzugreifen, bietet Groovy eine spezielle Syntax. | def primes = [ 2, 3, 5, 7] print primes[ 0 ] def dic = [ ‚rot‘ : ‚red‘, ‚blau‘ : ‚blue‘ ] print dic[‚rot‘] // red |
Die Operatoren ?. und ?: (Elvis-Operator) verhindern null-Zugriffe. | def name = ‚Chris‘ println name ?: ‚Kein Name‘ // Chris name = null println name ?: ‚Kein Name‘ // Kein Name |
Der Zugriff auf Zeichen über [] ist bei den Zeichenkettenklassen String, StringBuffer, StringBuilder möglich. | def s = ‚Ooog‘ print s[0] // O |
Der Zugriff über [] lässt auch Bereiche zu. | def s = „tutego“ print s[ 0, 1, 3..5 ] // tugeo def t = new StringBuilder( „tutego“ ) t[ 1..4 ] = „X“ print t // tXo |
Der Operator << hängt Dinge an Strings (Rückgabe ist dann StringBuffer), Listen oder Dateien an. | def s = ‚oger‘ def sb = ‚Das ist ‚ << s << ‚ oder?‘ print sb // Das ist oger oder? def file = new File(„out.txt“) file << „Zeile 1“ |
Reguläre Ausdrücke werden mit einer eigenen Syntax direkt von der Sprache unterstützt; =~ ist ein find, ==~ ein match. | print ‚2010‘ ==~ /\d+/ |
erweitertes switch-case etwa mit regulären Ausdrücken und Bereichen | switch ( 42 ) { case 0..100 : println ‚ist zwischen 0..100‘; break case Integer : println ‚ist Integer‘; break case { it % 2 == 0 }: println ‚ist gerade‘; break case ~/\d\d/: println ’42 passt auf das Pattern‘; break } |
Datentyp für Dauer und spezielle Eigenschaften für Datumswerte und überladene Operatoren zum leichten Rechnen mit dem Paket groovy.time | use ( groovy.time.TimeCategory ) { def today = new Date() def tomorrow = today + 1.day print „Morgen: $tomorrow, nächstes Jahr ${today + 1.year}“ } |
Closures als Codeblöcke werden unterstützt und finden überall in der Groovy-API Anwendung. | new File( „file.txt“ ).eachLine { println it } def names = [ „Charisma“, “ „, „Tina“, „“ ] print names.findAll { ! it.trim().isEmpty() } // [Charisma, Tina] |
Setter/Getter müssen nicht aufgerufen werden; beim Zugriff ref.property wird automatisch der Setter/Getter aufgerufen. | def p = new Point( 10, 20 ) print p.location.x // 10.0 |
In Methoden mit Rückgabe kann das Schlüsselwort return entfallen. | def add( a, b ) { a + b } |
Default-Parameter bei Methodendeklarationen | static tax( cost, taxRate = 19 ) { cost * taxRate / 100 } println tax( 100 ) // 19 println tax( 100, 7 ) // 7 |
Methoden und Klassen sind standardmäßig public, nicht paketsichtbar wie bei Java. Groovy erstellt automatisch Setter/Getter. | class Person { def name } |
Mit der Klassenannotation @Immutable wird ein Typ unveränderbar, mit @Singleton ein Singleton mit einem privaten Konstruktor und öffentlichem Attribut instance für die eine Instanz. | @Immutable class Pair { String val1, val2 } @Singleton class AppWindow { } |
Diverse Builder-Klassen erleichtern den Aufbau von hierarchischen XML- oder Swing-Bäumen ebenso wie Ant-Build-Skripten. | import groovy.xml.MarkupBuilder def writer = new StringWriter() new MarkupBuilder( writer ).html { head { title ‚Zählen mit Graf Zahl‘ } body { h1 ( ‚Willkommen‘ ) p { ul { (1..10).each { li it } } a( href:“’http://stupidedia.org/stupi/Graf_Zahl“‘, ‚Graf Zahl‘ ) } } } println writer |
Eigenschaften von Groovy mit Beispiel
Groovy-Skripte in Eclipse ausführen
Um Groovy-Skripte und Programme auszuführen, bieten sich drei Wege an:
- über eine spezielle Kommandozeile, die Groovy-Shell
- über das Eclipse-Plugin
- über die javax.script-API
Das Eclipse-Plugin unter http://groovy.codehaus.org/Eclipse+Plugin leistet gute Arbeit und wird ständig weiterentwickelt. Auf der Webseite ist der Update-Link genannt, sodass Groovy-Eclipse über den Update-Manager installiert werden kann.
- Wähle dazu Eclipse Help • Install New Software…
- In der Dialogbox fülle das Textfeld bei Work with mit dem Link http://dist.springsource.org/release/GRECLIPSE/e4.3/ (bzw. anderen Versionen je nach Eclipse-Version), und aktiviere Add…
- Aktiviere anschließend Groovy-Eclipse, und führe die Installation mit Next usw. zu Ende.
Ist Eclipse neu gestartet und das Plugin installiert, kann jedes Java-Projekt um Groovy-Unterstützung erweitert werden. Bei einem Java-Projekt aktiviert die Aktion Configure • Convert to Groovy Project im Kontextmenü genau diese Groovy-Unterstützung, sodass im Projektbaum die Groovy-Bibliotheken auftauchen.
File • New • Other… ermöglicht zum einen im Zweig Groovy das Erstellen eines neuen Groovy-Projekts (durch die Konvertierung eines existierenden Java-Projekts ist das nicht mehr nötig) und zum anderen mit Groovy Class das Erstellen einer Groovy-Klasse. Bei dieser Option lässt sich ein Paket- und Klassenname eingeben (etwa com.tutego.insel.script und GroovyBabe), und dann öffnet Eclipse den Groovy-Editor.
Löschen wir die Klassendeklaration und setzen nur die zwei Zeilen in die Datei:
package com.tutego.insel.script
print „Hallo Groovy“
Ausgeführt wird das Groovy-Skript im Kontextmenü (oder Run-Menü) mit Run As • Groovy Skript.
Groovy über die Skript-API ausführen
Um Groovy als Skriptsprache aus einem Java-Programm heraus zu nutzen, können wir wieder auf die Skript-API zurückgreifen. Wenn es sich bei Eclipse schon um ein Groovy-Projekt handelt, ist ein JAR schon im Klassenpfad eingebunden, und es ist nichts zu tun. Andernfalls bekommen wir von der Webseite http://groovy.codehaus.org/Download unter Download zip: Binary Release ein fast 30 MiB großes ZIP-Archiv wie groovy-binary-2.2.2.zip, wo groovy-all-2.2.2.jar im Ordner embeddable liegt und das wir in den Klassenpfad mit aufnehmen.
Ein kleines Beispiel:
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "groovy" );
System.out.println( engine.eval( "(1g..42g.gcd(56g)).sum()" ) ); // 105
[1] Bis auf sehr kleine Ausnahmen ist jedes Java-Programm ein Groovy-Programm.