当前位置: 首页 > news >正文

【Groovy】函数、闭包、泛型

1 函数

1.1 无参函数

1)常规调用

void myFun() {println("myFun")
}myFun() // 打印: myFun

2)字符串声明函数

void "myFun"() {println("myFun")
}myFun() // 打印: myFun

3)字符串调用函数

void myFun() {println("myFun")
}"myFun"() // 打印: myFun

1.2 有参函数

1)常规调用

void myFun(Integer num, String str) {println("$num, $str")
}myFun(5, "abc") // 打印: 5, abc

​ 在不引起歧义的情况下,可以省去小括号,如下。

void myFun(Integer num, String str) {println("$num, $str")
}myFun 5, "abc" // 打印: 5, abc

2)入参指定默认值

void myFun(String str = "abc") {println(str)
}myFun() // 打印: abc

1.3 有返回值函数

def add(int a, int b) {return a + b
}def c = add(3, 5)
println(c) // 打印: 8

1.4 可变长参数函数

1)常规调用

void myFun(String... params) {for (str in params) {println(str)}
}myFun("aa", "bb", "cc") // 打印: aa、bb、cc

​ 说明:函数的可变长参数个数最多为 1 个。

2)使用数组接收可变长参数

void myFun(String... params) {String[] arr = paramsprintln(arr.size())
}myFun("aa", "bb", "cc") // 打印: 3

3)将数组传给可变长参数函数

void myFun(String... params) {println(params.size())
}String[] arr = ["aa", "bb", "cc"]
myFun(*arr)  // 打印: 3
myFun("xx", *arr, "yy")  // 打印: 5

2 闭包

​ Groovy 中的闭包与 Java 中匿名函数(即没有名字的函数)有些类似,并且也提供了类似 Lambda 表达式的写法(详见 → Java 中 Lambda 表达式总结、Kotlin 中 Lambda 表达式)。

2.1 闭包的创建

2.1.1 通过 new 创建闭包

Closure myFun = new Closure(null) {int call(int a, int b) {return a + b}
}def res = myFun(3, 5)
println(res) // 打印: 8

2.1.2 通过 {} 创建闭包

1)无参闭包

def myFun = {println("myFun")
}myFun() // 打印: myFun

2)有参闭包

def myFun = { String str ->println("myFun, $str")
}myFun("abc") // 打印: myFun, abc

​ 闭包的入参类型可以省去,如下。

def myFun = { str ->println("myFun, $str")
}myFun("abc") // 打印: myFun, abc

​ 当闭包入参个数只有一个时,可以省去,引用时使用 it 替代,如下。

def myFun = {println("myFun, $it")
}myFun("abc") // 打印: myFun, abc

3)有返回值闭包

def myFun = { a, b ->return a + b
}def res = myFun(3, 5)
println(res) // 打印: 8

2.2 闭包对象封装函数

​ 本节主要介绍使用闭包对象封装一个函数。

2.2.1 使用 {} 封装函数

void test() {println("test")
}def myFun = { test() }
myFun() // 打印: test

2.2.2 使用 this.& 封装函数

1)无参函数

void test() {println("test")
}def myFun = this.&test
myFun() // 打印: test

2)有参函数

void test(int a, String b) {println("test, $a, $b")
}def myFun = this.&test
myFun(123, "abc") // 打印: test, 123, abc

3)有返回值函数

def test(int a, int b) {return a + b
}def myFun = this.&test
def res = myFun(3, 5)
println(res) // 打印: 8

2.3 函数参数是闭包

1)闭包无参

void outFun(Closure closure) {closure()
}outFun({println("inFun") // 打印: inFun
})

​ 当函数入参的最后一个参数是闭包时,可以将 {} 移到 () 外面(该方式称为尾随 Lambda 表达式);在不引起歧义的情况下,可以省去 (),如下。

void outFun(Closure closure) {closure()
}outFun {println("inFun") // 打印: inFun
}

2)闭包有参

void outFun(Closure closure) {closure("abc")
}outFun { a ->println(a) // 打印: abc
}

​ 当闭包入参个数只有一个时,可以省去,引用时使用 it 替代,如下。

void outFun(Closure closure) {closure("abc")
}outFun {println(it) // 打印: abc
}

3)闭包有返回值

void outFun(Closure closure) {def res = closure(3, 5)println(res)
}outFun { a, b ->a + b // 打印: 8
}

2.4 通过字符串调用对应函数

void myFun(String str, int num) {println("myFun, $str, $num")
}void test(String funName, String str, int num) {def method = this.&"$funName"method(str, num)
}test("myFun", "abc", 3) // 打印: myFun, abc, 3

3 泛型函数

​ 泛型的类型检查只存在于编译阶段,在源代码编译之后,不会保留任何关于泛型类型的内容,即类型擦除。

3.1 简单泛型函数

1)单泛型参数

<T> void myFun(T param) {println(param)
}myFun(123)  // 打印: 123
myFun("abc")  // 打印: abc
myFun(true)  // 打印: true
myFun(null)  // 打印: null

2)多泛型参数

<R, T, S> R myFun(T a, S b, R c) {println("$a, $b")return c
}def res = myFun("abc", 123, true) // 打印: abc, 123
println(res) // 打印: true

3.2 类中泛型函数

class MyClass<T> {void myFun(T a) {println(a)}
}def c1 = new MyClass<String>()
c1.myFun("abc") // 打印: abc
def c2 = new MyClass<Integer>()
c2.myFun(123) // 打印: 123

3.3 抗变、协变和逆变

​ Groovy 中不存在 Java 和 Kotlin 中的抗变、协变和逆变现象(详见 → 【Kotlin】函数)。

​ 如下,Integer 是 Number 的子类,Number 引用可以指向 Integer 对象,并且 Data 引用可以指向 Data 对象,Data 引用也可以指向 Data 对象,还可以访问、修改对象的泛型变量,这在 Java 和 Kotlin 中是不允许的。

class Data<T> {T valueData(T value) {this.value = value}
}Data<Integer> data1 = new Data<Integer>(1)
Data<Number> data2 = data1
data2.value = 10f
println(data2.value) // 打印: 10.0Data<Number> data3 = new Data<Number>(1.5f)
Data<Integer> data4 = data3
data4.value = 15
println(data4.value) // 打印: 15

3.4 泛型的界

​ Groovy 泛型中,可以为其指定上界。

1)单上界

class Data<T extends Number> {T valueData(T value) {this.value = value}
}Data<Integer> data1 = new Data<Integer>(1)
Data<String> data2 = new Data<String>("abc") // 运行错误, 指定了上界为Number

2)多上界

class A {}
interface B {}class C extends A implements B {}class Data<T extends A & B> {T valueData(T value) {this.value = value}
}def data = new Data(new C())

3.5 运行时检查泛型类型

​ Kotlin 中可以通过 inline 和 reified 关键字实现泛型类型检查(详见 → 【Kotlin】函数),它在编译阶段实现。

​ Groovy 是动态类型语言,类型检查在运行时进行,可以通过反射来实现类似的功能,如下。

<T> boolean isType(Class<T> type, value) {return type.isInstance(value)
}println(isType(Integer, "abc")) // 打印: false
println(isType(String, "abc"))  // 打印: true

​ 声明:本文转自【Groovy】函数、闭包、泛型。

http://www.hskmm.com/?act=detail&tid=22860

相关文章:

  • 关于onnxruntime依赖报错问题
  • 深度学习(Grad-CAM)
  • 论文选读
  • C++设计模式之行为型模式:职责链模式(Chain of Responsibility) - 实践
  • 第一章作业
  • 数据库系统概论
  • Pytorch
  • 页面 HTTPS 化实战,从证书部署到真机验证的全流程(证书链、重定向、混合内容、抓包排查) - 实践
  • AT_abc308_h [ABC308Ex] Make Q
  • 函数-高级用法+闭包
  • 点云-标注-分类-航线规划软件 (一)点云自动分类 - 实践
  • JVM的内存分配策略有哪些?
  • 在Linux系统上一键配置DoH,解决DNS解析被污染
  • 《电路基础》第五章学习笔记
  • Elasticsearch集群监控信息(亲测) - 教程
  • 2025超声波清洗机厂家TOP企业品牌推荐排行榜,龙门式,悬挂式,全自动,多臂式,多槽式,履带式,通过式,单槽式,摆动式,平移式超声波清洗机公司推荐!
  • SQL:concat函数(连接字符串)
  • 2025 北京地下室防潮品牌最新推荐排行榜:TOP3 实力品牌出炉,精准解决地下空间潮湿难题
  • python脚本统计fastq数据的GC含量
  • 第一次软件工程作业
  • 关于数颜色
  • 2025仿石漆厂家 TOP 企业品牌推荐排行榜,真石漆,水包砂,冠晶石,外墙,多彩,批刮,别墅,批发,出口仿石漆推荐这十家公司!
  • CF1615F LEGOndary Grandmaster
  • 2025 年仿石漆品牌最新推荐排行榜:聚焦真石漆仿石漆,水包砂仿石漆,冠晶石仿石漆,外墙仿石漆,多彩仿石漆供采购参考
  • 诚信液压阀块定制厂家推荐榜:实力制造与精准工艺口碑之选
  • 24 两两交换链表中的节点
  • 算法导论图论部分总结
  • 19 删除链表的倒数第 N 个结点
  • 浅谈 Bakas Trick / 不带删尺取 / 对顶栈
  • 聚变堆:中国BEST装置全面开建