×

Groovy 教程

Groovy 概述Groovy 环境Groovy 基本语法Groovy 数据类型Groovy 变量Groovy 运算符Groovy 循环Groovy 条件语句Groovy 方法Groovy 文件I/OGroovy 可选Groovy 数字Groovy 字符串Groovy 范围Groovy 列表Groovy 映射Groovy 日期和时间Groovy 正则表达式Groovy 异常处理Groovy 面向对象Groovy 泛型Groovy 特征Groovy 闭包Groovy 注释Groovy XMLGroovy JMXGroovy JSONGroovy DSLSGroovy 数据库Groovy 构建器Groovy 命令行Groovy 单元测试Groovy 模板引擎Groovy 元对象编程

Groovy 闭包


闭包是一个短的匿名代码块。它通常跨越几行代码。一个方法甚至可以将代码块作为参数。它们是匿名的。

下面是一个简单闭包的例子,它是什么样子。

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},这导致closure接受一个参数。当通过clos.call语句调用闭包时,我们现在可以选择将一个参数传递给闭包。

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

Hello World

下一个图重复了前面的例子并产生相同的结果,但显示可以使用被称为它的隐式单个参数。这里的'it'是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

使用映射闭包

以下示例显示了如何使用闭包。在下面的例子中,我们首先定义一个简单的关键值项Map。然后,映射集合类型定义一个名为.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 

闭包使用的方法

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

序号 方法和描述
1 find()

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

2 findAll()

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

3 any() & every()

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

4 collect()

该方法通过集合收集迭代,使用闭包作为变换器将每个元素转换为新值。


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)