Gradle系列三之Groovy基本语法

由于是学习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循环来讲。

  1. 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

以上就是闭包的委托策略。

喜欢本篇博客的简友们,就请来一波点赞,您的每一次关注,将成为我前进的动力,谢谢!

你可能感兴趣的:(Gradle系列三之Groovy基本语法)