Es scheint, als wäre Groovy in diesem Thread vergessen worden, also werde ich Groovy dieselbe Frage stellen.
- Versuchen Sie, die Antworten auf den Groovy-Kern zu beschränken
- Eine Funktion pro Antwort
- Geben Sie ein Beispiel und eine kurze Beschreibung der Funktion, nicht nur einen Link zur Dokumentation
- Beschriften Sie das Feature mit fettem Titel als erste Zeile
Siehe auch:
Mit der with- Methode können Sie Folgendes ändern:
myObj1.setValue(10) otherObj.setTitle(myObj1.getName()) myObj1.setMode(Obj1.MODE_NORMAL)
das mögen
myObj1.with { value = 10 otherObj.title = name mode = MODE_NORMAL }
quelle
myObj1.value = 10
(usw.) und letzterem, da Sie keine Setter-Methode aufrufen müssen?Verwenden von Hashes als Pseudoobjekte.
def x = [foo:1, bar:{-> println "Hello, world!"}] x.foo x.bar()
In Kombination mit der Eingabe von Enten können Sie mit diesem Ansatz einen langen Weg gehen. Sie müssen nicht einmal den "as" -Operator auspeitschen.
quelle
Kennt jemand Elvis ?
def d = "hello"; def obj = null; def obj2 = obj ?: d; // sets obj2 to default obj = "world" def obj3 = obj ?: d; // sets obj3 to obj (since it's non-null)
quelle
Das Herausfinden der Methoden für ein Objekt ist so einfach wie das Fragen der MetaClass:
"foo".metaClass.methods.name.sort().unique()
Drucke:
["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo", "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", "endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars", "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", "replaceAll", "replaceFirst", "split", "startsWith", "subSequence", "substring", "toCharArray", "toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]
quelle
Verwenden Sie Folgendes, um fehlende statische Methoden abzufangen
Foo { static A() { println "I'm A"} static $static_methodMissing(String name, args) { println "Missing static $name" } } Foo.A() //prints "I'm A" Foo.B() //prints "Missing static B"
- Ken
quelle
Destrukturierung
Es könnte in Groovy etwas anderes genannt werden; es heißt destructuring in clojure. Sie werden nie glauben, wie praktisch es sein kann.
def list = [1, 'bla', false] def (num, str, bool) = list assert num == 1 assert str == 'bla' assert !bool
quelle
Zum Testen von Java-Code mit Groovy ist der Object Graph Builder erstaunlich:
def company = builder.company( name: 'ACME' ) { address( id: 'a1', line1: '123 Groovy Rd', zip: 12345, state: 'JV' ) employee( name: 'Duke', employeeId: 1 ){ address( refId: 'a1' ) } }
Standardausstattung, aber trotzdem sehr schön.
ObjectGraphBuilder
(Sie müssen alle Eigenschaften Ihres POJO angeben, die ein
List
Standardwert einer leeren Liste sind, anstattnull
dass die Builder-Unterstützung funktioniert.)quelle
println """ Groovy has "multi-line" strings. Hooray! """
quelle
In Groovy 1.6 funktionieren reguläre Ausdrücke mit allen Abschlussiteratoren (wie jedem, Sammeln, Injizieren usw.) und ermöglichen Ihnen die einfache Arbeit mit den Erfassungsgruppen:
def filePaths = """ /tmp/file.txt /usr/bin/dummy.txt """ assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> "$file -> $path" } == ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
quelle
Im Gegensatz zu Java kann in Groovy alles in einer switch- Anweisung verwendet werden, nicht nur primitive Typen. In einer typischen eventPerformed- Methode
switch(event.source) { case object1: // do something break case object2: // do something break }
quelle
Verwenden des Raumschiff-Operators
Ich mag den Raumschiff-Operator , der für alle Arten von benutzerdefinierten Sortierszenarien nützlich ist. Einige Anwendungsbeispiele finden Sie hier . Eine Situation, in der es besonders hilfreich ist, besteht darin, einen Komparator im laufenden Betrieb eines Objekts mithilfe mehrerer Felder zu erstellen. z.B
def list = [ [ id:0, first: 'Michael', last: 'Smith', age: 23 ], [ id:1, first: 'John', last: 'Smith', age: 30 ], [ id:2, first: 'Michael', last: 'Smith', age: 15 ], [ id:3, first: 'Michael', last: 'Jones', age: 15 ], ] // sort list by last name, then first name, then by descending age assert (list.sort { a,b -> a.last <=> b.last ?: a.first <=> b.first ?: b.age <=> a.age })*.id == [ 3,1,0,2 ]
quelle
Durch das Schließen können alle alten Try-End-Spiele des Ressourcenmanagements verschwinden. Der Dateistream wird am Ende des Blocks automatisch geschlossen:
new File("/etc/profile").withReader { r -> System.out << r }
quelle
Die Funktionen, die durch die Transformationen im GDK-
groovy.transform
Paket bereitgestellt werden, wie z.@Immutable
: Die Annotation @Immutable weist den Compiler an, eine AST-Transformation auszuführen, die die erforderlichen Getter, Konstruktoren, Equals, HashCode und andere Hilfsmethoden hinzufügt, die normalerweise beim Erstellen unveränderlicher Klassen mit den definierten Eigenschaften geschrieben werden.@CompileStatic
: Dadurch kann der Groovy-Compiler Kompilierungszeitprüfungen im Java-Stil verwenden und dann eine statische Kompilierung durchführen, wodurch das Groovy-Metaobjektprotokoll umgangen wird.@Canonical
: Die Annotation @Canonical weist den Compiler an, eine AST-Transformation auszuführen, die Ihrer Klasse Positionskonstruktoren, Equals, HashCode und einen hübschen Druck toString hinzufügt.Andere:
@Slf4j
Diese lokale Transformation erweitert Ihr Programm um eine Protokollierungsfunktion mithilfe der LogBack-Protokollierung. Jeder Methodenaufruf für eine ungebundene Variable namens log wird einem Aufruf des Loggers zugeordnet.quelle
Sie können eine Liste mithilfe von toSpreadMap () in eine Karte konvertieren. Dies ist praktisch, wenn die Reihenfolge in der Liste ausreicht, um die Schlüssel und die damit verbundenen Werte zu bestimmen. Siehe Beispiel unten.
def list = ['key', 'value', 'foo', 'bar'] as Object[] def map = list.toSpreadMap() assert 2 == map.size() assert 'value' == map.key assert 'bar' == map['foo']
quelle
as Object []
in der ersten Zeile notwendig?Implementierung einer schließungsbasierten Schnittstelle
Wenn Sie eine typisierte Referenz haben wie:
Sie können die gesamte Schnittstelle implementieren mit:
foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface
Wenn Sie jede Methode separat implementieren möchten, können Sie alternativ Folgendes verwenden:
foo = [bar: {-> println "bar invoked"}, baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
quelle
null
Werte aus der Liste entfernendef list = [obj1, obj2, null, obj4, null, obj6] list -= null assert list == [obj1, obj2, obj4, obj6]
quelle
Ich weiß, dass ich etwas spät dran bin, aber ich denke, hier fehlen einige nette Funktionen:
Sammlung Plus / Minus-Operatoren
def l = [1, 2, 3] + [4, 5, 6] - [2, 5] - 3 + (7..9) assert l == [1, 4, 6, 7, 8, 9] def m = [a: 1, b: 2] + [c: 3] - [a: 1] assert m == [b: 2, c: 3]
Switch-Anweisung
switch (42) { case 0: .. break case 1..9: .. break case Float: .. break case { it % 4 == 0 }: .. break case ~/\d+/: .. break }
Bereiche und Indizierung
assert (1..10).step(2) == [1, 3, 5, 7, 9] assert (1..10)[1, 4..8] == [2, 5, 6, 7, 8, 9] assert ('a'..'g')[-4..-2] == ['d', 'e', 'f']
Unicode-Variablennamen
def α = 123 def β = 456 def Ω = α * β assert Ω == 56088
quelle
@Delegieren
class Foo { def footest() { return "footest"} } class Bar { @Delegate Foo foo = new Foo() } def bar = new Bar() assert "footest" == bar.footest()
quelle
In Literalen unterstreichen
Wenn Sie lange Literalzahlen schreiben, ist es für das Auge schwieriger herauszufinden, wie einige Zahlen zusammen gruppiert sind, z. B. mit Gruppen von Tausenden, Wörtern usw. Wenn Sie in Zahlenliteralen Unterstriche setzen können, ist es einfacher, diese Gruppen zu erkennen:
long creditCardNumber = 1234_5678_9012_3456L long socialSecurityNumbers = 999_99_9999L double monetaryAmount = 12_345_132.12 long hexBytes = 0xFF_EC_DE_5E long hexWords = 0xFFEC_DE5E long maxLong = 0x7fff_ffff_ffff_ffffL long alsoMaxLong = 9_223_372_036_854_775_807L long bytes = 0b11010010_01101001_10010100_10010010
quelle
Die Neuordnung von Argumenten mit impliziten Argumenten ist eine weitere nette Sache.
Dieser Code:
def foo(Map m=[:], String msg, int val, Closure c={}) { [...] }
Erstellt all diese verschiedenen Methoden:
foo("msg", 2, x:1, y:2) foo(x:1, y:2, "blah", 2) foo("blah", x:1, 2, y:2) { [...] } foo("blah", 2) { [...] }
Und mehr. Es ist unmöglich, Fehler zu machen, indem benannte und ordinale Argumente in die falsche Reihenfolge / Position gebracht werden.
Natürlich können Sie in der Definition von "foo" "String" und "int" von "String msg" und "int val" weglassen - ich habe sie nur aus Gründen der Klarheit belassen.
quelle
Ich denke, es ist eine Kombination von Abschlüssen als Parameter und Parameter-Standardwerte:
public void buyItems(Collection list, Closure except={it > 0}){ list.findAll(){except(it)}.each(){print it} } buyItems([1,2,3]){it > 2} buyItems([0,1,2])
Drucke: "312"
quelle
Verwenden des Spread-Operators in Methodenparametern
Dies ist eine große Hilfe beim Konvertieren von Code in Daten:
def exec(operand1,operand2,Closure op) { op.call(operand1,operand2) } def addition = {a,b->a+b} def multiplication = {a,b->a*b} def instructions = [ [1,2,addition], [2,2,multiplication] ] instructions.each{instr-> println exec(*instr) }
Hilfreich ist auch diese Verwendung:
String locale="en_GB" //this invokes new Locale('en','GB') def enGB=new Locale(*locale.split('_'))
quelle
Auswendiglernen
Memoization ist eine Optimierungstechnik, die darin besteht, die Ergebnisse teurer Funktionsaufrufe zu speichern und das zwischengespeicherte Ergebnis zurückzugeben, wenn die Funktion mit denselben Argumenten erneut aufgerufen wird.
Es gibt eine unbegrenzte Version, die jedes Paar (Eingabeargumente, Rückgabewert) zwischenspeichert, das jemals angezeigt wird. und eine eingeschränkte Version, die die letzten N Eingabeargumente und ihre Ergebnisse unter Verwendung eines LRU-Caches zwischenspeichert.
Auswendiglernen von Methoden:
import groovy.transform.Memoized @Memoized Number factorial(Number n) { n == 0 ? 1 : factorial(n - 1) } @Memoized(maxCacheSize=1000) Map fooDetails(Foo foo) { // call expensive service here }
Auswendiglernen von Schließungen:
def factorial = {Number n -> n == 0 ? 1 : factorial(n - 1) }.memoize() fooDetails = {Foo foo -> // call expensive service here }.memoizeAtMost(1000)
Die Wikipedia-Seite enthält umfangreiche Informationen zur Verwendung von Memoization in der Informatik. Ich werde nur auf eine einfache praktische Anwendung hinweisen.
Verschieben der Initialisierung einer Konstanten auf den letztmöglichen Moment
Manchmal haben Sie einen konstanten Wert, der zum Zeitpunkt der Klassendefinition oder Erstellung nicht initialisiert werden kann. Beispielsweise kann der Konstantenausdruck eine andere Konstante oder eine Methode aus einer anderen Klasse verwenden, die nach der Initialisierung Ihrer Klasse durch etwas anderes (Spring oder ähnliches) eingefügt wird.
In diesem Fall können Sie Ihre Konstante in einen Getter umwandeln und damit dekorieren
@Memoized
. Es wird nur einmal berechnet, beim ersten Zugriff und dann im zwischengespeicherten und wiederverwendeten Wert:import groovy.transform.Memoized @Memoized def getMY_CONSTANT() { // compute the constant value using any external services needed }
quelle
Groovy kann sehr ähnlich wie Javascript funktionieren. Sie können private Variablen und Funktionen über Closure haben. Sie können Funktionen auch mit Verschlüssen curry.
class FunctionTests { def privateAccessWithClosure = { def privVar = 'foo' def privateFunc = { x -> println "${privVar} ${x}"} return {x -> privateFunc(x) } } def addTogether = { x, y -> return x + y } def curryAdd = { x -> return { y-> addTogether(x,y)} } public static void main(String[] args) { def test = new FunctionTests() test.privateAccessWithClosure()('bar') def curried = test.curryAdd(5) println curried(5) } }
Ausgabe:
foo bar 10
quelle
Dynamischer Methodenaufruf
Sie können eine Methode mit einer Zeichenfolge mit ihrem Namen aufrufen
class Dynamic { def one() { println "method one()" } def two() { println "method two()" } } def callMethod( obj, methodName ) { obj."$methodName"() } def dyn = new Dynamic() callMethod( dyn, "one" ) //prints 'method one()' callMethod( dyn, "two" ) //prints 'method two()' dyn."one"() //prints 'method one()'
quelle
Wie erstelle ich einen JSON-Baum in ein paar Zeilen in Groovy?
1) Definieren Sie Ihren Baum mit selbstreferenziellem
withDefault
Abschlussdef tree // declare first before using a self reference tree = { -> [:].withDefault{ tree() } }
2) Erstellen Sie Ihren eigenen JSON-Baum
frameworks = tree() frameworks.grails.language.name = 'groovy' frameworks.node.language.name = 'js' def result = new groovy.json.JsonBuilder(frameworks)
Welches gibt:
{"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}
quelle
Sicherer Navigationsbetreiber
Der Operator "Sichere Navigation" wird verwendet, um eine NullPointerException zu vermeiden. Wenn Sie einen Verweis auf ein Objekt haben, müssen Sie möglicherweise überprüfen, ob dieser nicht null ist, bevor Sie auf Methoden oder Eigenschaften des Objekts zugreifen. Um dies zu vermeiden, gibt der sichere Navigationsoperator einfach null zurück, anstatt eine Ausnahme auszulösen, wie folgt:
def person = Person.find { it.id == 123 } // find will return a null instance def name = person?.name // use of the null-safe operator prevents from a NullPointerException, result is null
quelle
Verzögerung mehrerer Variablen
1) Mehrere Variablendeklarationen in einer Zeile
def (a,b,c) = [1,2,3]
2) Verwenden verschiedener Typdeklarationen.
def (String a, int b) = ['Groovy', 1]
quelle
Zwangsoperator
Der Zwangsoperator (as) ist eine Variante des Gießens. Zwang konvertiert Objekte von einem Typ in einen anderen, ohne dass sie für die Zuweisung kompatibel sind. Nehmen wir ein Beispiel:
Integer x = 123
String s = (String) x
Integer kann keinem String zugewiesen werden , daher wird zur Laufzeit eine ClassCastException erzeugt. Dies kann stattdessen durch Zwang behoben werden:
Ganzzahl x = 123 Zeichenfolge s = x als Zeichenfolge
Ganzzahl kann keiner Zeichenfolge zugewiesen werden, aber die Verwendung von as zwingt sie zu einer Zeichenfolge
quelle