May 14, 2021 Groovy
A closure is a short block of anonymous code. I t usually spans several lines of code. O ne method can even use blocks of code as arguments. They are anonymous.
Here's an example of a simple closure and what it looks like.
class Example { static void main(String[] args) { def clos = {println "Hello World"}; clos.call(); } }
In the example above, the line of code - "Hello World" is called a closure. Blocks of code referenced by this identifier can be executed using call statements.
When we run the program above, we will get the following results -
Hello World
Closures can also contain formal parameters to make them more useful, just like the method in Groovy.
class Example { static void main(String[] args) { def clos = {param->println "Hello ${param}"}; clos.call("World"); } }
In the code example above, be careful to use $s param, which causes the close to accept a parameter. When a closure is called through the close.call statement, we can now choose to pass an argument to the closure.
When we run the program above, we will get the following results -
Hello World
The next diagram repeats the previous example and produces the same result, but shows that you can use an implicit single parameter called it. The 'it' here is the keyword in Groovy.
class Example { static void main(String[] args) { def clos = {println "Hello ${it}"}; clos.call("World"); } }
When we run the program above, we will get the following results -
Hello World
More formally, closures can refer to variables when defining closures. Here's an example of how to do this.
class Example { static void main(String[] args) { def str1 = "Hello"; def clos = {param -> println "${str1} ${param}"} clos.call("World"); // We are now changing the value of the String str1 which is referenced in the closure str1 = "Welcome"; clos.call("World"); } }
In the example above, in addition to passing parameters to the closure, we also defined a variable called str1. Closures also accept variables and parameters.
When we run the program above, we will get the following results -
Hello World Welcome World
Closures can also be used as parameters for methods. In Groovy, many built-in methods for data types, such as lists and collections, have closures as parameter types.
The following example shows how to send a closure as an argument to a method.
class Example { def static Display(clo) { // This time the $param parameter gets replaced by the string "Inner" clo.call("Inner"); } static void main(String[] args) { def str1 = "Hello"; def clos = { param -> println "${str1} ${param}" } clos.call("World"); // We are now changing the value of the String str1 which is referenced in the closure str1 = "Welcome"; clos.call("World"); // Passing our closure to a method Example.Display(clos); } }
In the example above,
We define a static method called Display, which uses closures as arguments.
Then we define a closure in our main method and pass it as an argument to our Display method.
When we run the program above, we will get the following results -
Hello World Welcome World Welcome Inner
Several List, Map, and String methods accept a closure as an argument. Let's look at examples of how closures are used in these data types.
The following example shows how to use closures and lists. I n the following example, let's first define a simple list of values. list This function applies the closure as an argument and applies the closure to each element of the list
class Example { static void main(String[] args) { def lst = [11, 12, 13, 14]; lst.each {println it} } }
When we run the program above, we will get the following results -
11 12 13 14
The following example shows how to use a closure. I n the following example, we first define a simple key value item Map. ap. his function applies closures as arguments and applies closures to each key value pair of the map.
class Example { static void main(String[] args) { def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"] mp.each {println it} mp.each {println "${it.key} maps to: ${it.value}"} } }
When we run the program above, we get the following results -
TopicName = Maps TopicDescription = Methods in Maps TopicName maps to: Maps TopicDescription maps to: Methods in Maps
In general, we might want to traverse the members of a collection and apply some logic only if the elements meet some criteria. This is easy to handle with conditional statements in a closure.
class Example { static void main(String[] args) { def lst = [1,2,3,4]; lst.each {println it} println("The list will only display those numbers which are divisible by 2") lst.each{num -> if(num % 2 == 0) println num} } }
The example above shows the conditional if (num%2 s 0) expression used in the closure to check whether each item in the list can be divided by 2.
When we run the program above, we get the following results -
1 2 3 4 The list will only display those numbers which are divisible by 2. 2 4
The closure itself provides some methods.
Serial number | Method and description |
---|---|
1 |
find()
The find method finds the first value in the collection that matches a condition. |
2 |
findAll()
It finds all values in the receive object that match the closed condition. |
3 |
any() & every()
Method any iteration of each element of the collection, checking whether the Boolean predicate is valid for at least one element. |
4 |
collect()
The method collects iterations through a collection and uses closures as transformers to convert each element to a new value. |