Gradle必备--Groovy基础

Groovy是基于JVM虚拟机的一种动态语言,它的语法和Java非常相似,由Java入门Groovy,基本上没有任何障碍。Groovy完全兼容Java,又在此基础上增加了很多动态类型和灵活的特性,比如支持闭包,支持DSL,可以说它是一门非常灵活的动态脚本语言。

Groovy的特性虽然不多,但也有一些,我们不可能在这里都讲完,这也不是这本书的初衷,在这里我挑一些和Gradle有关的知识讲,让大家很快的入门Groovy,并且能看懂这门脚本语言,知道在Gradle为什么这么写。其次是每个Gradle的build脚本文件都是一个Groovy脚本文件,你可以在里面写任何符合Groovy的代码,比如定义类,生命函数,定义变量等等,而Groovy又完全兼容Java,这就意味着你可以在build脚本文件里写任何的Java代码,非常灵活方便。

字符串

字符串,每一门语言都会有对字符串的处理,Java相对要稍微复杂一些,限制比较多,相比而言,Groovy非常方便,比如字符串的运算、求值、正则等等。

从现在开始我们算是正式的介绍Groovy了,在此之前我们先要知道,在Groovy中,分号不是必须的。相信很多用Java的朋友都习惯了,没一行的结束必须有分号,但是Groovy每这个强制规定,所以你看到的Gradle脚本很多都没有分号,其实这个是Groovy的特性,而不是Gradle的。没有分号的时候,我们阅读的时候没一行默认为有分号就好了。

在Groovy中,单引号和双引号都可以定义一个字符串常量(Java里单引号定义一个字符),不同的是单引号标记的是纯粹的字符串常量,而不是对字符串里的表达式做运算,但是双引号可以。

task printStringClass << {
    defstr1 = '单引号'
    defstr2 = "双引号"
    println"单引号定义的字符串类型:"+str1.getClass().name
    println"双引号定义的字符串类型:"+str2.getClass().name
}

./gradlew printStringClass运行后我们能可以看到输出:

单引号定义的字符串类型:java.lang.String
双引号定义的字符串类型:java.lang.String

不管是单引号定义的还是双引号定义的都是String类型。
刚刚我们讲了单引号不能对字符串里的表达式做运算,下面我们看个例子:

task printStringVar << {
    defname = "张三"
    println'单引号的变量计算:${name}'
    println"单引号的变量计算:${name}"}

./gradlew printStringVar运行后输出:

单引号的变量计算:${name}单引号的变量计算:张三

可以看到,双引号标记的输出了我们想要的结果,但是单引号没有,所以大家可以记住了,单引号没有运算的能力,它里面的所有都是常量字符串。

双引号可以直接进行表达式计算的这个能力非常好用,我们可以用这种方式进行字符串链接运算,再也不用Java中繁琐的+号了。记住这个嵌套的规则,一个美元符号紧跟着一对花括号,花括号里放表达式,比如${name},${1+1}等等,只有一个变量的时候可以省略花括号,比如$name

集合

集合,也是我们在Java中经常用到的,Groovy完全兼容了Java的集合,并且进行了扩展,使得生命一个集合,迭代一个集合、查找集合的元素等等操作变得非常容易。常见的集合有ListSetMapQueue,这里我们只介绍常用的ListMap

List

在Java里,定义一个List,需要New一个实现了List接口的类,太繁琐,在Groovy中则非常简单。

task printList << { 
    def numList =[1,2,3,4,5,6];
    println numList.getClass().name
}

可以通过输出看到numList是一个ArrayList类型。

定义好集合了,怎么访问它里面的元素呢,像Java一样,使用get方法?太Low了,Groovy提供了非常简便的方法。

task printList << { 
    def numList =[1,2,3,4,5,6];
    println numList.getClass().name
    println numList[1]//访问第二个元素
    println numList[-1]//访问最后一个元素
    println numList[-2]//访问倒数第二个元素
    println numList[1..3]//访问第二个到第四个元素
}

Groovy提供下标索引的方式访问,就像数组一样,除此之外,还提供了负下标和范围索引。负下标索引代表从右边开始数,-1就代表从右侧数第一个,-2代表右侧数第二个,以此类推;1..3这种是一个范围索引,中间用两个.分开,这个会经常遇到。

除了访问方便之外,Groovy还为List提供了非常方便的迭代操作,这就是each方法,该方法接受一个闭包作为参数,可以访问List里的每个元素。

task printList << {
    def numList =[1,2,3,4,5,6];
    println numList.getClass().name

    println numList[1]//访问第二个元素
    println numList[-1]//访问最后一个元素
    println numList[-2]//访问倒数第二个元素
    println numList[1..3]//f访问第二个到第四个元素

    numList.each {
        println it
    }
}

it变量就是正在迭代的元素,这里有闭包的知识,我们可以先这么记住,后面详细讲。

Map

Map和List很像,只不过它的值是一个K:V键值对,所以在Groovy中Map的定义也非常简单。

task printlnMap << { 
    def map1 =['width':1024,'height':768]
    println map1.getClass().name
}

访问也非常灵活容易,采用map[key]或者map.key的方式都可以。

task printlnMap << {  
    def map1 =['width':1024,'height':768]
    println map1.getClass().name

    println map1['width']
    println map1.height
}

这两种方式都能快速的取出指定key的值,怎么样,比Java方便的多吧。

对于Map的迭代,当然也少不了each方法,只不过被迭代的元素是一个Map.Entry的实例。

task printlnMap << {
    def map1 =['width':1024,'height':768]
    println map1.getClass().name

    println map1['width']
    println map1.height

    map1.each {
        println "Key:${it.key},Value:${it.value}"
    }
}

对于集合,Groovy还提供了诸如collect、find、findAll等便捷的方法,有兴趣的朋友可以找相关文档看一下,这里就不一一讲了。

方法

方法大家都不陌生,这里特别用一节讲的目的主要是讲Groovy方法和Java的不同,然后我们才能看明白我们的Gradle脚本里的代码,突然发现,原来这是一个方法调用啊!

括号是可以省略的

我们在Java中调用一个方法都是invokeMethod(parm1,parm2),非常规范,Java就是这么中规中矩的语言,在Groovy中就要灵活的多,可以省略()变成这样invokeMethod parm1,parm2 是不是觉得非常简洁,这在定义DSL的时候非常有用,书写也非常方便。

task invokeMethod << {
    method1(1,2)
    method1 1,2

}
def method1(int a,int b){
    println a+b
}

上例中这两种调用方式的结果是一样的,有没有觉得第二种更简洁的多,Gradle中的方法调用都是这种写法。

return是可以不写的

在Groovy中,我们定义有返回值的方法时,return语句不是必须的,当没有return的时候,Groovy会把方法执行过程中的最后一句代码作为其返回值。

task printMethodReturn << {
    def add1 = method2 1,2
    def add2 = method2 5,3
    println "add1:${add1},add2:${add2}"

}
def method2(int a,int b){
   if(a>b){
        a
    }else{
        b
    }
}
```groovy
执行`./gradlew printMethodReturn`后可以看到输出:

```bash
add1:2,add2:5

从例子中可以看出,当a作为最后一行被执行的代码时,a就是该方法的返回值,反之则是b。

代码块是可以作为参数传递的

代码块—一段被花括号包围的代码,其实就是我们后面要将的闭包,Groovy是允许其作为参数传递的,但是结合这我们上面方法的特性,最后的基于闭包的方法调用就会非常优雅、易读。以我们的集合的each方法为例,它接受的参数其实就是一个闭包。

//基于死板的写法其实是这样
numList.each({println it})
//我们格式化一下,是不是好看一些
numList.each({
    println it
})
//好看一些,Groovy规定,如果方法的最后一个参数是闭包,可以放到方法外面
numList.each(){
    println it
}
//然后方法可以省略,就变成我们经常看到的啦
numList.each {
    println it
}

了解了这个演进方式,你再看到类似的这样的写法就明白了,原来是一个方法调用,以此类推,你也知道怎么定义一个方法,让别人这么调用。

JavaBean

JavaBean是一个非常好的概念,你现在看到的组件化、插件化、配置集成等都是基于JavaBean。在Java中为了访问和修改JavaBean的属性,我们不得不重复的生成getter/setter方法,并且使用他们,太麻烦,太繁琐,这在Groovy中得到很大的改善。

task helloJavaBean << {
    Person p = new Person()

    println "名字是:${p.name}"
    p.name = "张三"
    println "名字是:${p.name}"
}
class Person {
    private String name
}

在没有给name属性赋值的时候,输出是null,赋值后,输出的就是“张三”了,通过上面例子,我们发现,我们在Groovy可以非常容易的访问和修改JavaBean的属性值,而不用借助getter/setter方法,这是因为Groovy都帮我们搞定了。

在Groovy中,并不是一定要定义成员变量,才能作为类的属性访问,我们直接getter/setter方法,也一样可以当做属性访问。

task helloJavaBean << {
    Person p = new Person()

    println "名字是:${p.name}"
    p.name = "张三"
    println "名字是:${p.name}"
    println "年龄是:${p.age}"}
class Person {
    private String name
    public int getAge(){ 
           12
    }
}

通过上面的例子我们可以发现,我并没有定义一个age的成员变量,但是我一样可以通过p.age获取到该值,这是因为我们定义了getAge()方法。那么这时候我们能不能修改age的值呢?答案是不能的,因为我们没有为其定义setter方法。

在Gradle中你会见到很多这种写法,你开始以为这是该对象的一个属性,其实只是因为该对象里定义了相应的getter/setter方法而已。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容