(3)Groovy语法

【Groovy语法规则】

下面是Groovy的一个简单的代码示例:

public class ProjectVersion {
    private int major; //大版本
    private int minor; //小版本
    public ProjectVersion(int major, int minor) {
        this.major = major;
        this.minor = minor  // Groovy分号是可选的
    }
    public int getMajor() {
        major  // Groovy最后一个表达式的值会作为返回值
    }
    public void setMajor(int major) {
        this.major = major;
    }
    // Groovy自动为属性添加getter和setter方法
}

ProjectVersion v1 = new ProjectVersion(1,1);
v1.minor = 2  // 直接使用.获取对象
println v1.minor

ProjectVersion v2 = null;
println v2 == v2;  //不会抛出空指针异常,因为Groovy中==和equals()方法一样

我们看到,GroovyBeanExample只定义了一个私有的minor属性,并没有getter和setter。但是在使用时,我们可以直接对minor进行访问,无论时读还是写。事实上,我们并不是在直接访问minor进属性,当我们执行"v1.minor = 2"时,我们实际调用的是"v1.setMinor(2)",而在调用"println v1.minor"时,我们实际调用的是"println v1.getMinor()"。

这里的原因在于,Groovy动态地为minor创建了getter和setter,采用像直接访问的方式的目的是为了增加代码的可读性,使它更加自然,而在内部,Groovy依然是在调用setter和getter方法。

【高效的Groovy特性】

1. 可选的类型定义

def version = 1

def类似于JavaScript中的var,不是一个变量类型,它定义一个变量,但是这个变量的类型是自动推出来的。def可省略。

2. assert

assert version = 2

3. 括号是可选的

Groovy中函数调用的时候还可以不加括号。比如:

println(version)
println version

4.字符串

字符串有三种形式:

// 单引号:仅仅是一个字符串
def s1 = 'gradle'
// 双引号:可以插入一个变量
def s2 = "gradle version is ${version}"
//三个单引号:可以换行
def s3 = '''my 
name is 
gradle'''

5. 集合API

(1)list

def buildTool = ['ant','maven']
buildTool << 'gradle'  // 往list中追加元素
assert buildTool.getClass() == AarrayList
assert buildTool.size() == 3

(2)map

def buildYears = ['ant':2000,'maven':2004]
buildYears.gradle = 2009 // 往map中追加元素
// 获取map中元素有两种形式
println buildYears.ant
println buildYears['gradle']

6. 闭包

闭包就是一个代码块。闭包的定义格式:

{ [closureParameters -> ] statements }

闭包的参数列表是可选的,参数的类型也是可选的。如果我们不指定参数的类型,会由编译器自动推断。下面介绍在Groovy种常见的闭包使用方式。

创建闭包有三种方法:

//(1)使用 def 声明一个闭包
// 1.1 包含参数的闭包,箭头后面就是代码块
def c1 = {
    v ->
        print v
}

// 1.2 不包含参数的闭包
def c1 = {
    print 'hello'
}

 //(2)使用指定类型 Closure 声明一个闭包
 Closure callback = { println 'Done!' }     

 //(3)使用泛型 声明一个固定返回类型的闭包
 Closure<Boolean> isTextFile = {
    File it -> it.name.endsWith('.txt') //返回boolean类型
} 

使用闭包作为参数的方法:

def method1(Closure closure){
      closure('prarm')  // 执行带参数的闭包
}

def method2(Closure closure){
      closure()  // 执行不带参数的闭包
}

// 执行方法
method1(c1);
method2(c2);

下面给出一个groovy的文件进行讲解:

// 构建脚本中都是有个Projet实例的(项目实例)
apply plugin:'java'  // apply是Project实例的一个方法,调用apply()方法和调用project.apply()方法的效果是一样的;Groovy中函数调用的时候可以不加括号;plugin参数的值等于java

version = '0.1' // version这个属性的值为0.1

repositories{    // repositories是一个方法;{mavenCentral()}是一个闭包
  mavenCentral()
}

dependencies{
   compile 'commons-codec:commons-codec:1.6'
}

【delegate机制】

Gradle大量地使用了Groovy闭包的delegate机制。简单来说,delegate机制可以使我们将一个闭包中的执行代码的作用对象设置成任意其他对象。比如:

class Child {
   private String name
}

class Parent {
   Child child = new Child();

   void configChild(Closure c) {
      c.delegate = child
      c.setResolveStrategy Closure.DELEGATE_FIRST
      c()
   }
}

def parent = new Parent()
parent.configChild {
name = "child name"
}

println parent.child.name

在上面的例子中,当我们调用configChild()方法时,我们并没有指出name属性是属于Child的,但是它的确是在设置Child的name属性。事实上光从该方法的调用中,我们根本不知道name是属于哪个对象的,你可能会认为它是属于Parent的。真实情况是,在默认情况下,name的确被认为是属于Parent的,但是我们在configChild()方法的定义中做了手脚,使其不再访问Parent中的name(Parent也没有name属性),而是Child的name。在configChild()方法中,我们将该方法接受的闭包的delegate设置成了child,然后将该闭包的ResolveStrategy设置成了DELEGATE_FIRST。这样,在调用configChild()时,所跟闭包中代码被代理到了child上,即这些代码实际上是在child上执行的。

此外,闭包的ResolveStrategy在默认情况下是OWNER_FIRST,即它会先查找闭包的owner(这里即parent),如果owner存在,则在owner上执行闭包中的代码。这里我们将其设置成了DELEGATE_FIRST,即该闭包会首先查找delegate(本例中即child),如果找到,该闭包便会在delegate上执行。

你可能会发现,在使用Gradle时,我们并没有像上面的parent.configChild()一样指明方法调用的对象,而是在build.gradle文件中直接调用task(),apply()和configuration()方法等,这是因为在没有说明调用对象的情况下,Gradle会自动将调用对象设置成当前Project。比如调用apply()方法和调用project.apply()方法的效果是一样的。查查Gradle的Project文档,你会发现这些方法都是Project类的方法。

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

推荐阅读更多精彩内容