78

It seems like Groovy was forgotten in this thread so I'll just ask the same question for Groovy.

  • Try to limit answers to Groovy core
  • One feature per answer
  • Give an example and short description of the feature, not just a link to documentation
  • Label the feature using bold title as the first line

See also:

  1. Hidden features of Python
  2. Hidden features of Ruby
  3. Hidden features of Perl
  4. Hidden features of Java
Community
  • 1
  • 1

31 Answers31

56

Using the spread-dot operator

def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]

This is a shortcut for animals.collect { it.size() }.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
39

The with method allows to turn this:

 myObj1.setValue(10)
 otherObj.setTitle(myObj1.getName())
 myObj1.setMode(Obj1.MODE_NORMAL)

into this

 myObj1.with {
    value = 10
    otherObj.title = name
    mode = MODE_NORMAL
 }
Rui Vieira
  • 5,253
  • 5
  • 42
  • 55
  • 3
    that brings me old memories about object pascal :-) – fortran Sep 07 '09 at 07:29
  • 1
    Given this is Groovy, wouldn't a more typical comparison be between `myObj1.value = 10` (etc.) and the latter, since you don't need to invoke a setter method? – Philip Feb 08 '15 at 04:31
37

Using hashes as pseudo-objects.

def x = [foo:1, bar:{-> println "Hello, world!"}]
x.foo
x.bar()

Combined with duck typing, you can go a long way with this approach. Don't even need to whip out the "as" operator.

Robert Fischer
  • 1,436
  • 12
  • 26
37

Anyone know about 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)
r5d
  • 579
  • 5
  • 24
billjamesdev
  • 14,554
  • 6
  • 53
  • 76
  • 1
    is this the same as the null coalescing operator (??) from C#? – Alex Baranosky Mar 09 '10 at 06:25
  • It would seem so, yes, though I had to look up the C# op. – billjamesdev Mar 09 '10 at 06:47
  • Not exactly, It is a shortened ternary operator. I did a writeup on it: http://colinharrington.net/blog/2008/10/groovy-elvis-operator/ You can also do full expressions in there :-) – Colin Harrington Dec 13 '10 at 05:29
  • The code posted in the answer doesn't compile because a keyword, "default", is being used as a variable. Use "d" instead to make the code compile. – Vorg van Geir Aug 15 '11 at 12:31
  • @gotomanners You bolded the "Elvis" in the answer text an hour ago. Any particular reason for this, besides perhaps causing the question to appear at the top of the Groovy Tagged Questions page? – Vorg van Geir Aug 15 '11 at 12:41
  • 2
    No important reason at all, just keeping with the convention that the OP suggested. At the time I didn't take into consideration the refreshing effect my action would cause. – gotomanners Aug 15 '11 at 12:49
35

Finding out what methods are on an object is as easy as asking the metaClass:

"foo".metaClass.methods.name.sort().unique()

prints:

["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"]
Dónal
  • 185,044
  • 174
  • 569
  • 824
Ted Naleid
  • 26,511
  • 10
  • 70
  • 81
  • 1
    This seems silly at first. But it's incredibly useful. In python you have the dir built-in function: dir("foo") gives all methods for a string. – santiagobasulto Jun 06 '12 at 20:39
28

To intercept missing static methods use the following

 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

Jonas Eicher
  • 1,413
  • 12
  • 18
ken
  • 3,745
  • 6
  • 34
  • 49
  • New to Groovy, having a bit of difficulty parsing this. – ripper234 Oct 22 '10 at 06:15
  • 3
    The Object Foo does not have a static method named B defined. Yet you can implement one on the fly by adding a method called "$static_methodMissing(String, Object)" and implementing whatever you want there. This magic method is called whenever a static method is invoked and the object does not have that static method defined. – Jen S. Feb 14 '11 at 09:12
24

Destructuring

It might be called something else in Groovy; it's called destructuring in clojure. You'll never believe how handy it can come.

def list = [1, 'bla', false]
def (num, str, bool) = list
assert num == 1
assert str == 'bla'
assert !bool
  • It's called [multiple assignment](http://groovy.codehaus.org/Multiple+Assignment) in Groovy. Wikipedia calls it [parallel assignment](http://en.wikipedia.org/wiki/Assignment_%28computer_science%29#Parallel_assignment). – Frank Kusters Feb 25 '15 at 09:38
  • Destructuring in Clojure is much more powerful than multiple assignment. http://clojure.org/special_forms#Special%20Forms--Binding%20Forms%20(Destructuring) – Jason Apr 09 '15 at 00:34
21

For testing java code with groovy, object graph builder is amazing:

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' )
   }
}

Standard feature, but still really nice.

ObjectGraphBuilder

(You do need to give any properties of your POJO that are Lists a default value of an empty list rather than null for builder support to work.)

Eel Lee
  • 3,513
  • 2
  • 31
  • 49
krosenvold
  • 75,535
  • 32
  • 152
  • 208
19
println 
"""
Groovy has "multi-line" strings.
Hooray!
"""
undefined
  • 6,208
  • 3
  • 49
  • 59
John Flinchbaugh
  • 2,338
  • 1
  • 17
  • 20
  • Ah, the beauty of multi-line strings. Every language should adopt these. – ripper234 Oct 22 '10 at 06:14
  • 2
    Not sure why a multi-line string needs " " " as a delimiter when " could have been extended to allow multi-line as well as single-line strings. – Vorg van Geir Aug 15 '11 at 12:45
  • 2
    @VorgvanGeir using """ means you don't have to escape ". – undefined Aug 27 '12 at 21:51
  • 1
    @Brian True, but """a\bc"de"f\g""" doesn't compile because you have to escape the \ or \g, and the \b will act like a backspace unless you escape it. What's the point in not needing to escape " when you still need to escape EVERY other special sequence inside a string? – Vorg van Geir Aug 28 '12 at 04:26
  • Because some of us want to be able to write "foo\tbar". But Groovy also has: println (/a\bc"de"f\g/) // -> a\bc"de"f\g – DarkStar Jul 29 '14 at 16:37
15

Unlike Java, in Groovy, anything can be used in a switch statement, not just primitive types. In a typical eventPerformed method

switch(event.source) {
   case object1:
        // do something
        break
   case object2:
        // do something
        break
}
Rui Vieira
  • 5,253
  • 5
  • 42
  • 55
15

In groovy 1.6, regular expressions work with all of the closure iterators (like each, collect, inject, etc) and allow you to easily work with the capture groups:

def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""

assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> 
        "$file -> $path"
    } ==  ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
Ted Naleid
  • 26,511
  • 10
  • 70
  • 81
15

Using the Spaceship Operator

I like the Spaceship operator, useful for all sorts of custom sorting scenarios. Some examples of usage are here. One situation in which it's particularly helpful is in creating a comparator on the fly of an object using multiple fields. e.g.

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 ]
mmigdol
  • 2,023
  • 1
  • 18
  • 20
14

Closures can make all the old try-finally games of resource management go away. The file stream is automatically closed at the end of the block:

new File("/etc/profile").withReader { r ->
    System.out << r
}
John Flinchbaugh
  • 2,338
  • 1
  • 17
  • 20
  • 1
    And also the filehandle is properly closed in the event of an Exception being raised within the closure, I like this even better than try-with-resources. – DarkStar Jul 29 '14 at 16:54
13

The features provided by the transformations inside the GDK's groovy.transform package, such as:

  • @Immutable: The @Immutable annotation instructs the compiler to execute an AST transformation which adds the necessary getters, constructors, equals, hashCode and other helper methods that are typically written when creating immutable classes with the defined properties.
  • @CompileStatic: This will let the Groovy compiler use compile time checks in the style of Java then perform static compilation, thus bypassing the Groovy meta object protocol.
  • @Canonical: The @Canonical annotation instructs the compiler to execute an AST transformation which adds positional constructors, equals, hashCode and a pretty print toString to your class.

Others:

  • @Slf4j This local transform adds a logging ability to your program using LogBack logging. Every method call on a unbound variable named log will be mapped to a call to the logger.
  • Groovy's XML Slurper: easy parsing of XML. Killer feature!
Hans Westerbeek
  • 5,645
  • 3
  • 34
  • 35
12

You can convert a list to a map by using toSpreadMap(), convenient at times when the order in the list is enough to determine the keys and the values associated with them. See example below.

def list = ['key', 'value', 'foo', 'bar'] as Object[]
def map = list.toSpreadMap()

assert 2 == map.size()
assert 'value' == map.key
assert 'bar' == map['foo']
ken
  • 3,745
  • 6
  • 34
  • 49
12

Closure-Based Interface Implementation

If you have a typed reference such as:

MyInterface foo

You can implement the entire interface using:

foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface

Alternatively, if you want to implement each method separately, you can use:

foo = [bar: {-> println "bar invoked"}, 
    baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
Dónal
  • 185,044
  • 174
  • 569
  • 824
8

Remove null values from list

def list = [obj1, obj2, null, obj4, null, obj6]
list -= null
assert list == [obj1, obj2, obj4, obj6]
BIdesi
  • 341
  • 2
  • 12
7

@Delegate

class Foo {
    def footest() { return "footest"}   
}

class Bar {
    @Delegate Foo foo = new Foo()     
}

def bar = new Bar()

assert "footest" == bar.footest()
Eel Lee
  • 3,513
  • 2
  • 31
  • 49
Omnipresent
  • 29,434
  • 47
  • 142
  • 186
7

I know I'am a bit late but I think there are some nice features missing here:

Collection plus/minus operators

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 statement

switch (42) {
  case 0: .. break
  case 1..9: .. break
  case Float: .. break
  case { it % 4 == 0 }: .. break
  case ~/\d+/: .. break
}

Ranges and indexing

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 variable names

def α = 123
def β = 456
def Ω = α * β
assert Ω == 56088
micha
  • 47,774
  • 16
  • 73
  • 80
6

Underscore in literals

When writing long literal numbers, it’s harder on the eye to figure out how some numbers are grouped together, for example with groups of thousands, of words, etc. By allowing you to place underscore in number literals, it’s easier to spot those groups:

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
Pankaj Shinde
  • 3,361
  • 2
  • 35
  • 44
5

Argument reordering with implicit arguments is another nice one.

This code:

def foo(Map m=[:], String msg, int val, Closure c={}) {
  [...]
}

Creates all these different methods:

foo("msg", 2, x:1, y:2)
foo(x:1, y:2, "blah", 2)
foo("blah", x:1, 2, y:2) { [...] }
foo("blah", 2) { [...] }

And more. It's impossible to screw up by putting named and ordinal arguments in the wrong order/position.

Of course, in the definition of "foo", you can leave off "String" and "int" from "String msg" and "int val" -- I left them in just for clarity.

Robert Fischer
  • 1,436
  • 12
  • 26
  • I wish this were the case, but currently Groovy (1.6) only supports named arguments for object constructors. You can use this syntax for method calls, but it packages any named arguments up into a Map, then looks for foo(Map). – Cody Casterline Sep 08 '09 at 21:19
  • I'm confused as to what you think I said that implied different. – Robert Fischer Jan 04 '10 at 21:17
4

Using the spread operator in method parameters

This is a great help when converting code to data:

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)
}

Also helpful is this usage:

String locale="en_GB"

//this invokes new Locale('en','GB')
def enGB=new Locale(*locale.split('_'))
Luis Muñiz
  • 4,649
  • 1
  • 27
  • 43
  • No, I mean converting code to data, making an array which is data, equivalent to a list of arguments, which normally is static. But I get your point, it depends on your perspective. I'm looking at it from the point of vue of refactoring existing static code to more dynami!c code. – Luis Muñiz Jul 31 '13 at 09:20
  • Perhaps "when using a data-driven design"? – DarkStar Jul 29 '14 at 17:03
4

I think it's a combination of closures as parameter and parameter-default-values:

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])

prints: "312"

Grim
  • 1,938
  • 10
  • 56
  • 123
3

Memoization

Memoization is an optimization technique that consists in storing the results of expensive function calls and returning the cached result whenever the function is called again with the same arguments.

There is an unlimited version, that will cache ever pair of (input arguments, return value) it will ever see; and a limited version, that will cache the last N input arguments seen and their results, using a LRU cache.

Memoization of methods:

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
}

Memoization of closures:

def factorial = {Number n ->
    n == 0 ? 1 : factorial(n - 1)
}.memoize()

fooDetails = {Foo foo ->
    // call expensive service here
}.memoizeAtMost(1000)

The Wikipedia page has extensive information on the uses of Memoization in Computer Science. I will just point out one simple practical use.

Deferring the initialization of a constant to the last possible moment

Sometimes you have a constant value that cannot be initialized at class definition or creation time. For example, the constant expression may make use of another constant or a method from a different class, which will be plugged in by something else (Spring or such) after the initialization of your class.

In this case, you can convert your constant into a getter and decorate it with @Memoized. It will only be computed once, the first time it's accessed, and then the value cached and reused:

import groovy.transform.Memoized

@Memoized
def getMY_CONSTANT() {
    // compute the constant value using any external services needed
}
Tobia
  • 17,856
  • 6
  • 74
  • 93
2

Groovy can work a lot like Javascript. You can have private vars and functions via closure. You can also curry functions with closures.

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)
}
}

output:

foo bar 10

Jason
  • 406
  • 1
  • 5
  • 16
2

Dynamic method invocation

You can invoke a method using a string with its name

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()'
lifeisfoo
  • 15,478
  • 6
  • 74
  • 115
2

How to build a JSON tree in a couple of lines in groovy ?

1) define your tree with self-referential withDefault closure

def tree // declare  first before using a self reference
tree = { ->  [:].withDefault{ tree() } }

2) Create your own JSON tree

frameworks = tree()
frameworks.grails.language.name = 'groovy'
frameworks.node.language.name = 'js'

def result =  new groovy.json.JsonBuilder(frameworks)

Which gives: {"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}

ludo_rj
  • 3,877
  • 1
  • 18
  • 37
2

Safe navigation operator

The Safe Navigation operator is used to avoid a NullPointerException. Typically when you have a reference to an object you might need to verify that it is not null before accessing methods or properties of the object. To avoid this, the safe navigation operator will simply return null instead of throwing an exception, like so:

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
Pankaj Shinde
  • 3,361
  • 2
  • 35
  • 44
1

Multiple variables deceleration

1)Multiple variables declarations in single line

def (a,b,c) = [1,2,3]

2)Using different type declarations.

def (String a, int b) = ['Groovy', 1]
0

Elvis operator

"Elvis operator" is a shortening of the ternary operator. One instance of where this is handy is for returning a 'sensible default' value if an expression resolves to false(as in Groovy truth). A simple example might look like this:

with the ternary operator, you have to repeat the value you want to assign

displayCity = user.city ? user.city: 'UnKnown City'

with the Elvis operator, the value, which is tested, is used if it is not false

displayCity = user.city ?: 'UnKnown City'
Kamil
  • 506
  • 4
  • 9
  • 21
Ishwor
  • 181
  • 2
  • 10
0

Coercion operator

The coercion operator (as) is a variant of casting. Coercion converts object from one type to another without them being compatible for assignment. Let’s take an example:

Integer x = 123
String s = (String) x
Integer is not assignable to a String, so it will produce a ClassCastException at runtime This can be fixed by using coercion instead:

Integer x = 123 String s = x as String
Integer is not assignable to a String, but use of as will coerce it to a String

Ishwor
  • 181
  • 2
  • 10