由于是学习Groovy基础语法,开始我选择的IDE是Intellij IDEA,大家可以选择其它IDE,但是都需要配置Groovy环境变量和Java环境变量,这里就不一一赘述了。
Groovy中变量
Groovy没有基本类型,对于一些像int类型都会被包装成对象类型Integer
int x = 1
println(x.class)
def y = 3.14
println(y.class)
y = 'hello groovy'
println(y.class)
打印输出如下:
class java.lang.Integer
class java.math.BigDecimal
class java.lang.String
如果一个变量只在本类使用,可以直接用def去定义该变量;如果该变量还被其他类使用,那么最好还是直接用具体的类型定义该变量,而不是用def去定义。
Groovy中字符串
def name = 'name one'
def doubleName = "name double"
def tripleName = '''name triple'''
println name.class
println doubleName.class
println tripleName.class
打印输出如下:
class java.lang.String
也就是说,在一般的情况下,这三者都是可以表示字符串的,但是也有部分区别,比如:
def sayHello = "Hello: ${name}" //可扩展做任意的表达式
println sayHello.class
println sayHello
打印输出如下:
class org.codehaus.groovy.runtime.GStringImpl
Hello: name one
只有双引号才可以做这种扩展,注意这里的类型是GStringImpl,也就是GString的实现类。
对于三引号,也有其他两者做不到的,比如,按照某个规则显示:
def tripleName = '''\
line one
line two
line three\
'''
打印输出如下:
line one
line two
line three
对于一些字符串方法,字符串填充center、padLeft;比较大小str > str2;reverse()、capitalize()、isNumber(),这些方法在这里就不做赘述了,大家可以自行尝试。
逻辑控制
由于这里if/else和while循环和Java程序使用相似,故这里只选switch/case和for循环来讲。
- switch/case
def n = 1.23
def result
switch (n) {
case 'hello':
result = 'find hello'
break
case 'groovy':
result = 'find groovy'
break
case [1, 2, 3, 'hello groovy']: //列表
result = 'find list'
break
case 12..30:
result = 'find range' //范围
break
case Integer:
result = 'find integer'
break
case BigDecimal:
result = 'find bigDecimal'
break
default:
result = 'find default'
break
}
println result
打印输出如下:
find bigDecimal
for循环
def sum = 0
for (i in 0..9) {
sum += i
}
sum = 0
//对List的循环
for (i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
sum += i
}
sum = 0
//对Map进行循环
for (i in ['合肥':1, '杭州':2, '南京':3]) {
sum += i.value
}
println sum
闭包
闭包是Groovy的一个非常重要的特性,可以说它是DSL的基础。闭包不是Groovy的首创,但是它支持这一重要特性,这就使代码灵活、轻量、可复用,再也不用像Java一样动不动就要用一个类了。
def clouser = {
println 'Hello groovy!'
}
这种写法就是闭包,我们可以怎样调用闭包呢?
clouser.call()
clouser()
上面这两种写法都可以调用闭包。闭包内还可以传入参数:
def clouser = {String language ->
println "Hello $language"
}
闭包内默认有一个it值,用于默认参数:
def clouser = {
println "Hello ${it}"
}
clouser.call('groovy!')
clouser('groovy!')
闭包一定是有返回值的,而且默认是花括号中的最后一行:
def clouser = {String language ->
"Hello ${language}"
}
def word = clouser('groovy!')
println word
打印输出如下:
Hello groovy!
接下来我们来验证返回值是否就是花括号的最后一行:
def clouser = {String language ->
"Hello ${language}"
'Hello Java!'
}
def word = clouser('groovy!')
println word
打印输出如下:
Hello Java!
输出结果也就验证了花括号的最后一行就是返回值。
闭包的使用
求累积:
int fun(int number) {
def result = 1
1.upto(number, {num -> result *= num})
return result
}
println fun(5)
还可以这样写:
int fun(int number) {
def result = 1
1.upto(number) {
num -> result *= num
}
return result
}
求累加:
int fun2(int number) {
def result = 1
number.times {
num -> result += num
}
return result
}
println fun2(5)
要注意,这里只是累加到4,也就是1+0+1+2+3+4 = 11
字符串与闭包结合使用
1.字符串的each函数:
def str = 'the 2 add 3 is 5'
str.each {
temp -> print temp
}
打印输出如下:
the 2 add 3 is 5
2.字符串的find函数:
def finder = str.find {
it.isNumber()
}
println finder
打印输出如下:
2
也就是说find函数式查找字符串中符合闭包条件的第一个元素,找到了就直接返回。
3.字符串的findAll函数:
println str.findAll {
it.isNumber()
}
打印输出如下:
[2, 3, 5]
4.字符串的any函数:
println str.any {
it.isNumber()
}
打印输出如下:
true
只要有一个元素符合闭包的条件,就返回true
5.字符串的every函数:
println str.every {
it.isNumber()
}
打印输出如下:
false
当所有的元素都符合闭包条件的时候,才返回true
6.字符串的collect函数:
println str.collect {
it.toUpperCase()
}
打印输出如下:
[T, H, E, , 2, , A, D, D, , 3, , I, S, , 5]
闭包进阶
闭包的三个重要变量:this、owner、delegate
def scriptClouser = {
println "scriptClouser this:" + this //代表闭包定义处的类
println "scriptClouser owner:" + owner //代表闭包定义处的类或者对象
println "scriptClouser delegate:" + delegate //代表任意对象,默认与owner一致
}
scriptClouser.call()
打印输出如下:
scriptClouser this:VariableStudy@3efa6afc
scriptClouser owner:VariableStudy@3efa6afc
scriptClouser delegate:VariableStudy@3efa6afc
this、owner、delegate三者代表同一个对象VariableStudy实例对象
接下来,我们初始化一个内部类Person:
class Person {
def classClouser = {
println "classClouser this:" + this
println "classClouser owner:" + owner
println "classClouser delegate:" + delegate
}
def say() {
def classClouser = {
println "methodClouser this:" + this
println "methodClouser owner:" + owner
println "methodClouser delegate:" + delegate
}
classClouser.call()
}
}
Person p = new Person()
p.classClouser.call()
p.say()
打印输出如下:
classClouser this:Person@6ccead66
classClouser owner:Person@6ccead66
classClouser delegate:Person@6ccead66
methodClouser this:Person@6ccead66
methodClouser owner:Person@6ccead66
methodClouser delegate:Person@6ccead66
this、owner、delegate三者还是表示同一个对象Person实例对象
现在我们在闭包中再定义一个闭包:
def nestClouser = {
def innerClouser = {
println "innerClouser this:" + this
println "innerClouser owner:" + owner
println "innerClouser delegate:" + delegate
}
innerClouser.call()
}
nestClouser.call()
打印输出如下:
innerClouser this:VariableStudy@a072d8c
innerClouser owner:VariableStudy$_run_closure9@44d88759
innerClouser delegate:VariableStudy$_run_closure9@44d88759
这时候this表示的是类VariableStudy的实例对象,而owner和delegate都表示内部闭包中的实例化对象innerClouser。
那么如何修改delegate和owner不一样呢?
def nestClouser = {
def innerClouser = {
println "innerClouser this:" + this
println "innerClouser owner:" + owner
println "innerClouser delegate:" + delegate
}
innerClouser.delegate = p //修改默认的delegate
innerClouser.call()
}
nestClouser.call()
打印输出如下:
innerClouser this:VariableStudy@55dee8d0
innerClouser owner:VariableStudy$_run_closure9@239494f6
innerClouser delegate:Person@52765b39
总结:
1.在类或者方法中定义闭包,那么this、owner、delegate都是一样的(默认不改变delegate);
2.如果在闭包中又嵌套一个闭包,那么this、owner、delegate将不再一样,this将指向闭包定义处外层的实例变量或者类本身(最接近的);而owner和delegate都会指向最近的闭包对象;
3.只有人为的修改delegate,delegate和owner才会不一样(this和owner不可以修改)
闭包的委托策略
class Student {
String name
def pretty = {
"my name is ${name}"
}
}
class Teacher {
String name
}
Student stu = new Student(name: "John")
Teacher tea = new Teacher(name: "jack")
println stu.pretty.call()
打印输出如下:
my name is John
接下来我们做如下的修改:
class Student {
String name
def pretty = {
"my name is ${name}"
}
}
class Teacher {
String name
}
Student stu = new Student(name: "John")
Teacher tea = new Teacher(name: "jack")
stu.pretty.delegate = tea
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println stu.pretty.call()
打印输出如下:
my name is jack
以上就是闭包的委托策略。
喜欢本篇博客的简友们,就请来一波点赞,您的每一次关注,将成为我前进的动力,谢谢!