Closures are a powerful way of passing around blocks of executable code. Think of closures as being like anonymous inner classes in Java that have only a single (anonymous) method.
Closures can be used as an alternative to using iterators; where the container is in full control.
Using closures can make the handling of exceptions and the closing of resources much simpler.
For a good example of this see Groovy SQL
Closures compared to anonymous inner classes
One difference from anonymous inner classes in Java is that Groovy supports true closures where state can be passed into and out of closures. Any local variables in scope when the closure is created can be used and modified and any variables created within the closure are visible outside as local variables. No 'final' keyword is required like with Java and annonymous inner classes.
Consider the following code
Notice that count goes from the outer scope to the inner scope and back out again after being modified.
The ast variable goes from inside scope out.
Closures are normal objects
Closures are objects that can be passed around and called on demand. So you can do things like this
Each closure is compiled to a new class which is derived from Closure.
The above is syntax sugar for.
A closure can take an arbitrary number of parameters like normal Java/Groovy methods. By default a closure takes a single parameter whose name defaults to being called 'it'. You can specify any name(s) you wish using a parameter list clause at the start of the closure declaration.
Here is another example of using closures with 2 parameters with the inject() method which is useful for aggregation.
You can see more documentation on closures here