Parece que Groovy fue olvidado en este hilo, así que solo haré la misma pregunta para Groovy.
- Intenta limitar las respuestas al núcleo de Groovy
- Una característica por respuesta
- Dé un ejemplo y una breve descripción de la función, no solo un enlace a la documentación.
- Etiquete la función con un título en negrita como primera línea
Ver también:
El método with permite convertir esto:
myObj1.setValue(10) otherObj.setTitle(myObj1.getName()) myObj1.setMode(Obj1.MODE_NORMAL)
dentro de esto
myObj1.with { value = 10 otherObj.title = name mode = MODE_NORMAL }
fuente
myObj1.value = 10
(etc.) y este último, ya que no necesita invocar un método de establecimiento?Usando hashes como pseudoobjetos.
def x = [foo:1, bar:{-> println "Hello, world!"}] x.foo x.bar()
Combinado con la escritura de pato, puede recorrer un largo camino con este enfoque. Ni siquiera necesita sacar el operador "como".
fuente
Alguien sabe sobre 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)
fuente
Averiguar qué métodos hay en un objeto es tan fácil como preguntarle a la metaclase:
"foo".metaClass.methods.name.sort().unique()
huellas dactilares:
["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"]
fuente
Para interceptar los métodos estáticos que faltan, utilice lo siguiente
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
fuente
Desestructuración
Podría llamarse de otra manera en Groovy; se llama desestructuración en clojure. Nunca creerá lo útil que puede resultar.
def list = [1, 'bla', false] def (num, str, bool) = list assert num == 1 assert str == 'bla' assert !bool
fuente
Para probar el código java con groovy, el generador de gráficos de objetos es increíble:
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' ) } }
Característica estándar, pero muy agradable.
ObjectGraphBuilder
(Debe proporcionar cualquier propiedad de su POJO que sea
List
un valor predeterminado de una lista vacía en lugar denull
que funcione el soporte del constructor).fuente
println """ Groovy has "multi-line" strings. Hooray! """
fuente
En groovy 1.6, las expresiones regulares funcionan con todos los iteradores de cierre (como cada uno, recopilar, inyectar, etc.) y le permiten trabajar fácilmente con los grupos de captura:
def filePaths = """ /tmp/file.txt /usr/bin/dummy.txt """ assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> "$file -> $path" } == ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
fuente
A diferencia de Java, en Groovy, cualquier cosa se puede usar en una declaración de cambio , no solo tipos primitivos. En un evento típico Método realizado
switch(event.source) { case object1: // do something break case object2: // do something break }
fuente
Usando el operador de nave espacial
Me gusta el operador Spaceship , útil para todo tipo de escenarios de clasificación personalizados. Algunos ejemplos de uso están aquí . Una situación en la que es particularmente útil es crear un comparador sobre la marcha de un objeto utilizando varios campos. p.ej
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 ]
fuente
Los cierres pueden hacer que desaparezcan todos los viejos juegos de la gestión de recursos. La secuencia de archivos se cierra automáticamente al final del bloque:
new File("/etc/profile").withReader { r -> System.out << r }
fuente
Las características proporcionadas por las transformaciones dentro de los GDK
groovy.transform
paquete , como:@Immutable
: La anotación @Immutable indica al compilador que ejecute una transformación AST que agrega los getters, constructores, equals, hashCode y otros métodos auxiliares necesarios que normalmente se escriben al crear clases inmutables con las propiedades definidas.@CompileStatic
: Esto permitirá que el compilador Groovy utilice comprobaciones en tiempo de compilación al estilo de Java y luego realice una compilación estática, evitando así el protocolo de metaobjetos Groovy.@Canonical
: La anotación @Canonical indica al compilador que ejecute una transformación AST que agrega constructores posicionales, equals, hashCode y una bonita impresión toString a su clase.Otros:
@Slf4j
Esta transformación local agrega una capacidad de registro a su programa mediante el registro LogBack. Cada llamada a un método en una variable independiente denominada log se asignará a una llamada al registrador.fuente
Puede convertir una lista en un mapa usando toSpreadMap (), conveniente en momentos en que el orden en la lista es suficiente para determinar las claves y los valores asociados con ellas. Vea el ejemplo a continuación.
def list = ['key', 'value', 'foo', 'bar'] as Object[] def map = list.toSpreadMap() assert 2 == map.size() assert 'value' == map.key assert 'bar' == map['foo']
fuente
as Object []
en primera línea?Implementación de interfaz basada en cierres
Si tiene una referencia escrita como:
Puede implementar toda la interfaz usando:
foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface
Alternativamente, si desea implementar cada método por separado, puede usar:
foo = [bar: {-> println "bar invoked"}, baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
fuente
Eliminar
null
valores de la listadef list = [obj1, obj2, null, obj4, null, obj6] list -= null assert list == [obj1, obj2, obj4, obj6]
fuente
Sé que llegué un poco tarde, pero creo que faltan algunas características interesantes aquí:
Colección más / menos operadores
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]
Declaración de cambio
switch (42) { case 0: .. break case 1..9: .. break case Float: .. break case { it % 4 == 0 }: .. break case ~/\d+/: .. break }
Rangos e indexación
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']
Nombres de variables Unicode
def α = 123 def β = 456 def Ω = α * β assert Ω == 56088
fuente
@Delegar
class Foo { def footest() { return "footest"} } class Bar { @Delegate Foo foo = new Foo() } def bar = new Bar() assert "footest" == bar.footest()
fuente
Subrayar en literales
Al escribir números literales largos, es más difícil de entender cómo se agrupan algunos números, por ejemplo, con grupos de miles, de palabras, etc. Al permitirle colocar un guión bajo en literales numéricos, es más fácil detectar esos grupos:
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
fuente
El reordenamiento de argumentos con argumentos implícitos es otro buen método.
Este código:
def foo(Map m=[:], String msg, int val, Closure c={}) { [...] }
Crea todos estos métodos diferentes:
foo("msg", 2, x:1, y:2) foo(x:1, y:2, "blah", 2) foo("blah", x:1, 2, y:2) { [...] } foo("blah", 2) { [...] }
Y más. Es imposible equivocarse poniendo argumentos ordinales y con nombre en el orden / posición incorrectos.
Por supuesto, en la definición de "foo", puede omitir "String" e "int" de "String msg" e "int val"; los dejé solo para mayor claridad.
fuente
Creo que es una combinación de cierres como parámetro y valores predeterminados de parámetro:
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])
impresiones: "312"
fuente
Usar el operador de propagación en los parámetros del método
Esta es una gran ayuda al convertir código en datos:
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) }
También es útil este uso:
String locale="en_GB" //this invokes new Locale('en','GB') def enGB=new Locale(*locale.split('_'))
fuente
Memorización
La memorización es una técnica de optimización que consiste en almacenar los resultados de costosas llamadas a funciones y devolver el resultado en caché cada vez que se vuelve a llamar a la función con los mismos argumentos.
Hay una versión ilimitada, que almacenará en caché cada par de (argumentos de entrada, valor de retorno) que verá; y una versión limitada, que almacenará en caché los últimos N argumentos de entrada vistos y sus resultados, utilizando una caché LRU.
Memorización de métodos:
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 }
Memorización de cierres:
def factorial = {Number n -> n == 0 ? 1 : factorial(n - 1) }.memoize() fooDetails = {Foo foo -> // call expensive service here }.memoizeAtMost(1000)
La página de Wikipedia tiene amplia información sobre los usos de la memorización en informática. Solo señalaré un uso práctico simple.
Diferir la inicialización de una constante hasta el último momento posible
A veces, tiene un valor constante que no se puede inicializar en la definición de la clase o en el momento de la creación. Por ejemplo, la expresión constante puede hacer uso de otra constante o un método de una clase diferente, que será conectado por otra cosa (Spring o similar) después de la inicialización de su clase.
En este caso, puede convertir su constante en un captador y decorarlo con
@Memoized
. Solo se calculará una vez, la primera vez que se acceda, y luego el valor se almacenará en caché y se reutilizará:import groovy.transform.Memoized @Memoized def getMY_CONSTANT() { // compute the constant value using any external services needed }
fuente
Groovy puede funcionar de manera muy similar a Javascript. Puede tener variables y funciones privadas mediante el cierre. También puede curry funciones con cierres.
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) } }
salida:
foo bar 10
fuente
Invocación de método dinámico
Puedes invocar un método usando una cadena con su nombre
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()'
fuente
¿Cómo construir un árbol JSON en un par de líneas en groovy?
1) define tu árbol con
withDefault
cierre autorreferencialdef tree // declare first before using a self reference tree = { -> [:].withDefault{ tree() } }
2) Crea tu propio árbol JSON
frameworks = tree() frameworks.grails.language.name = 'groovy' frameworks.node.language.name = 'js' def result = new groovy.json.JsonBuilder(frameworks)
Lo que da:
{"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}
fuente
Operador de navegación seguro
El operador Safe Navigation se utiliza para evitar una NullPointerException. Normalmente, cuando tiene una referencia a un objeto, es posible que deba verificar que no sea nulo antes de acceder a los métodos o propiedades del objeto. Para evitar esto, el operador de navegación segura simplemente devolverá nulo en lugar de lanzar una excepción, así:
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
fuente
Desaceleración de múltiples variables
1) Declaraciones de múltiples variables en una sola línea
def (a,b,c) = [1,2,3]
2) Uso de declaraciones de tipos diferentes.
def (String a, int b) = ['Groovy', 1]
fuente
Operador de coacción
El operador de coerción (as) es una variante del casting. La coerción convierte el objeto de un tipo a otro sin que sean compatibles para la asignación. Tomemos un ejemplo:
Integer x = 123
String s = (String) x
Integer no se puede asignar a una String, por lo que producirá una ClassCastException en tiempo de ejecución.Esto se puede arreglar usando coerción en su lugar:
Integer x = 123 String s = x como String
Integer no se puede asignar a una String, pero el uso de as lo forzará a una String
fuente