闭包(Closures)

优质
小牛编辑
134浏览
2023-12-01

闭包是一个简短的匿名代码块。 它通常只包含几行代码。 方法甚至可以将代码块作为参数。 他们本质上是匿名的。

以下是一个简单闭包的例子,它看起来像什么。

class Example {
   static void main(String[] args) {
      def clos = {println "Hello World"};
      clos.call();
   } 
}

在上面的例子中,代码行 - {println“Hello World”}被称为闭包。 可以使用call语句执行此标识符引用的代码块。

当我们运行上述程序时,我们将得到以下结果 -

Hello World

闭包中的形式参数

闭包还可以包含形式参数,以使它们像Groovy中的方法一样更有用。

class Example {
   static void main(String[] args) {
      def clos = {param->println "Hello ${param}"};
      clos.call("World");
   } 
}

在上面的代码示例中,请注意$ {param}的使用,这会导致闭包获取参数。 通过clos.call语句调用闭包时,我们现在可以选择将参数传递给闭包。

当我们运行上述程序时,我们将得到以下结果 -

Hello World

下一个插图重复前一个示例并生成相同的结果,但显示可以使用称为它的隐式单个参数。 这里'它'是Groovy中的关键字。

class Example {
   static void main(String[] args) {
      def clos = {println "Hello ${it}"};
      clos.call("World");
   } 
}

当我们运行上述程序时,我们将得到以下结果 -

Hello World

闭包和变量

更正式地说,闭包可以在定义闭包时引用变量。 以下是如何实现这一目标的示例。

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

在上面的例子中,除了将参数传递给闭包之外,我们还定义了一个名为str1的变量。 闭包还带有变量和参数。

当我们运行上述程序时,我们将得到以下结果 -

Hello World 
Welcome World

在方法中使用闭包

闭包也可以用作方法的参数。 在Groovy中,许多内置的数据类型方法(如列表和集合)都将闭包作为参数类型。

以下示例显示如何将闭包作为参数发送到方法。

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

在上面的例子中,

  • 我们定义了一个名为Display的静态方法,它将闭包作为参数。

  • 然后我们在main方法中定义一个闭包,并将它作为参数传递给Display方法。

当我们运行上述程序时,我们将得到以下结果 -

Hello World 
Welcome World 
Welcome Inner

集合和字符串中的闭包

几个List,Map和String方法接受闭包作为参数。 让我们看一下如何在这些数据类型中使用闭包的示例。

使用带有列表的闭包

以下示例显示了如何将闭包与列表一起使用。 在下面的示例中,我们首先定义一个简单的值列表。 然后列表集合类型定义一个名为的函数。 each 。 此函数将闭包作为参数,并将闭包应用于列表的每个元素。

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      lst.each {println it}
   } 
}

当我们运行上述程序时,我们将得到以下结果 -

11 
12 
13 
14

使用带有地图的闭包

以下示例显示了如何将闭包与Maps一起使用。 在下面的示例中,我们首先定义一个简单的键值项映射。 然后,地图集合类型定义了一个名为.each的函数。 此函数将闭包作为参数,并将闭包应用于映射的每个键值对。

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

当我们运行上述程序时,我们将得到以下结果 -

TopicName = Maps 
TopicDescription = Methods in Maps 
TopicName maps to: Maps 
TopicDescription maps to: Methods in Maps

通常,我们可能希望迭代集合的成员并仅在元素满足某些标准时应用某些逻辑。 这可以通过闭包中的条件语句来处理。

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

上面的示例显示了闭包中使用的条件if(num%2 == 0)表达式,用于检查列表中的每个项目是否可被2整除。

当我们运行上述程序时,我们将得到以下结果 -

1 
2 
3 
4 
The list will only display those numbers which are divisible by 2.
2 
4 

与闭包一起使用的方法

闭包本身提供了一些方法。

Sr.No.方法和描述
1find()

find方法在集合中查找与某个条件匹配的第一个值。

2findAll()

它查找接收对象中与闭包条件匹配的所有值。

3any()&every()

方法any遍历集合的每个元素,检查布尔谓词是否对至少一个元素有效。

4collect()

方法collect遍历集合,使用闭包作为变换器将每个元素转换为新值。