一、变量与字符串
java 语法在Groovy文件中可以用。
1、强类型
强类型直接用变量类型申明变量
弱类型可以用def 申明变量 ,编译器自动识别类型,弱类型用之前必须初始化,强类型可以不初始化。
int x = 1
char y = 'a'
2、弱类型
弱类型用def关键字定义
def x = 1
def y = 'A'
弱类型的定义必须初始化,不然编译器不知该怎么初始化该变量。
弱类型可以随意进行类型转换,只要是能转的类型,比如将char转为String。
3.String的定义的3种方式
def name1 = 'abc'
def name2 = "defg"
def name3 = '''hijkml'''
第一种单引号的用法跟java没有任何区别
第二种双引号,可以用$符号进行字符串拼接,也可以进行运算,如
def sum = "${3+2}"
println("sum 的值是$sum")
输出结果
sum 的值是5
第三种三引号可以完整原样得将用户输入的内容显示,比如在单引号中需要用“\n”来实现换行效果,三引号中直接用回车即可。
groovy中的字符串还可以做减法
def name1 = "abc"
def name2 = "abcdefg"
println(name2-name1)
输出结果是
defg
String还有跟Java类似的一系列的API,大家都可以自己去尝试下
二、闭包的基础用法
匿名内联函数,也称为一个闭包。本质上,闭包是将函数内部和函数外部连接起来的桥梁。
简单点讲,可以将闭包看作是将函数申明为变量,这个变量可以传递,也可以直接调用,从而执行闭包里面的代码块
def closure = {//闭包的申明方式
println("我是闭包")
}
closure()//闭包的调用方式1
println("______________________")
closure.call()//闭包的调用方式2
以上
输出结果:
我是闭包
______________________
我是闭包
以上是无参数的闭包,现在我们看看有参数的闭包
def closure = {
String name,int age->//参数和函数体之间用->隔开
println("我是有参的闭包,我的名字是$name, 我的年龄是 $age")
}
closure.call("BB",18)
输出结果是
我是有参的闭包,我的名字是BB, 我的年龄是 18
上面我们看到了无参和有参的闭包,现在我们看看默认参数的闭包
def closure = {
println("我是默认参数的闭包,我的名字是$it")//无参的闭包中都用一个默认的参数it
}
closure.call("MB")
闭包也可以有返回值,跟函数的返回值一样,在函数体的最后通过return返回,在调用的时候接收 ,这里就举例了。
闭包作为内联函数的使用
int a = fab(5)
int fab(int num){
int result = 1
1.upto(num,{number->result *= number})
return result
}
println(a)
如果是第一次接触闭包,看到上面的代码可能会有点懵,接下来我们会一步步解释。
upto是int提供的函数,参数有2个,第一个是num,第二个是闭包,这里相当于申明了一个匿名函数,只是申明,这个闭包的调用在upto函数体里面。我们再看看upto函数
public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
int self1 = self.intValue();
int to1 = to.intValue();
if (self1 > to1) {
throw new GroovyRuntimeException("The argument (" + to + ") to upto() cannot be less than the value (" + self + ") it's called on.");
} else {
for(int i = self1; i <= to1; ++i) {
closure.call(i);
}
}
}
我们看到upto这里接收可3个参数,第一个参数self是前面调用的1,第二个参数才是我们传入的num,第三个参数是我们传入的闭包,可以看到我们传入的闭包,在for循环里面调用了,并传入了参数i。看for循环是将传入的参数self由1逐渐变大,也就是这里调用upto实现的效果就是用1*2*3*4*5,输出结果是
120
同理这里int的api还有downto,可将传入参数由大变小进行运算
三、闭包中的三个重要变量this、owner、delegate
让我们先看看这样一份代码
def closure1 = {
println("我是 closure1 this ="+this)
println("我是 closure1 owner ="+owner)
println("我是 closure1 delegate ="+delegate)
def closure2 ={
println("我是 closure2 this ="+this)
println("我是 closure2 owner ="+owner)
println("我是 closure2 delegate ="+delegate)
def closure3 ={
println("我是 closure3 this ="+this)
println("我是 closure3 owner ="+owner)
println("我是 closure3 delegate ="+delegate)
}
closure3.call()
}
closure2.call()
}
closure1.call()
看看运行结果
我是 closure1 this =TestString@38089a5a
我是 closure1 owner =TestString@38089a5a
我是 closure1 delegate =TestString@38089a5a
我是 closure2 this =TestString@38089a5a
我是 closure2 owner =TestString$_run_closure1@54e7df6a
我是 closure2 delegate =TestString$_run_closure1@54e7df6a
我是 closure3 this =TestString@38089a5a
我是 closure3 owner =TestString$_run_closure1$_closure2@77128536
我是 closure3 delegate =TestString$_run_closure1$_closure2@77128536
- this是带边闭包定义处的类,即如果是闭包里面嵌套闭包,内层闭包的this只能代表内层。这个跟java 中的this和内部类的机制差不多,应该不难理解。
- owner和delegate现在看上去没有什么区别,都代表当前闭包的上一个闭包
我们再在上面定义closure3 的下面加两行代码,将字符串“abc”赋值给closure3的delegate和owner
closure3.owner = "abc"
closure3.delegate = "abc"
在看看打印结果
我是 closure3 owner =TestString$_run_closure1$_closure2@6b88ca8c
我是 closure3 delegate =abc
owner 和delegate 的区别就是delegate 能手动修改赋值成任何对象,而owner 则不能。
那么delegate 这么设计有什么用呢?
让我们看看下面一份代码
class Worker{
String name
}
class Student{
String name;
def introducte = {
println("我是 $name")
}
String toString(){
introducte.call()
}
}
def student = new Student(name:"小强")
def worker = new Worker(name:"Michael")
/*student.introducte.delegate = worker
student.introducte.resolveStrategy = Closure.DELEGATE_FIRST*/
student.introducte.call()
输出结果为
我是 小强
这里应该没什么疑问,name的取值是student 的。如果我们把注释的两行代码放开,看看输出结果
我是 Michael
通过解开注释的两行代码,我们设置委托策略delegate 优先,闭包就会从它现有delegate 中去找传入参数,执行程序,也就直接从worker 中取name值。