主页 > 软件开发  > 

【Groovy】函数、闭包、泛型

【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 = params println(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<Number> 引用可以指向 Data<Integer> 对象,Data<Integer> 引用也可以指向 Data<Number> 对象,还可以访问、修改对象的泛型变量,这在 Java 和 Kotlin 中是不允许的。

class Data<T> { T value Data(T value) { this.value = value } } Data<Integer> data1 = new Data<Integer>(1) Data<Number> data2 = data1 data2.value = 10f println(data2.value) // 打印: 10.0 Data<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 value Data(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 value Data(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】函数、闭包、泛型由讯客互联软件开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【Groovy】函数、闭包、泛型