Groovy for Gradle users

    Gradle的核心功能是用Java建立的。在此之上是用动态语言Groovy编写的domain specific language(DSL)。当编写一个Gradle构建脚本时,你自动地就使用了由该DSL暴露出来的语言结构来表达你的构建指令。Gradle构建脚本是可执行的Groovy脚本,但它们不能被Groovy运行时运行。当实现定制逻辑的需求出现时,你可以使用Groovy的语言特性直接在Gradle构建脚本中建立出想要的功能。本文是Groovy语言的入门读物,并解释了为什么Gradle用户学习Groovy很重要。后面,我还会说明Gradle的配置元素是如何用Groovy实现的。

1、Groovy是什么?

    Groovy是一门动态编程语言。它的语法和Java的很相近。它集成了已有的Java类和库,这使得Java开发人员学习Groovy很容易。Groovy不仅是在Java的强大之上建立起来的,它还提供了受到Ruby、Python以及其他语言启发的强大编程特性。Groovy可以被用作为一个脚本语言而无需编译。Groovy代码也可以被编译成java字节码。

2、我需要知道多少Groovy知识

    编写首个构建脚本的话,知道那么一点就行了。然而,强烈建议你要知道一些Java。Groovy几乎百分百兼容Java。当实现不重要的琐碎的任务,你可以选择编写Java代码或是使用Groovy的富于表现力的语言结构。

    先来看一个例子。假设你想要确定某个目录中所有的文件,并将这些文件的名字写到一个新文件allfiles.txt中。听起来很简单,对吧?下面是task action doLast的Java版。

task appendFilenames << {                                       
   File inputDirectory = new File("src");                     
   File outputFile = new File(getBuildDir(), "allfiles.txt"); 
   File outputDirectory = outputFile.getParentFile();         
   if(!outputDirectory.exists()) {                            
      outputDirectory.mkdirs();                               
   }                                                          
   outputFile.createNewFile();                                
   FileWriter fileWriter = new FileWriter(outputFile, true);  
   try {                                                      
      for(File file : inputDirectory.listFiles()) {           
         fileWriter.write(file.getName() + "\n");             
      }                                                       
   }                                                          
   finally {                                                  
      fileWriter.close();                                     
   }                                                          
}

    可以看出来,除了任务定义本身是用Gradle的DSL定义的,不需要任何Groovy代码。再来看看Groovy版的代码(更简短):

task appendFilenames << {                                    
   def inputDirectory = new File('src')                   
   def outputFile = new File(buildDir, 'allfiles.txt')    
   def outputDirectory = outputFile.parentFile            
   if(!outputDirectory.exists()) {                        
      outputDirectory.mkdirs()                            
   }                                                      
   outputFile.createNewFile()                             
   inputDirectory.eachFile { outputFile << "$it.name\n" } 
}

    对于更复杂(包含定制任务以及插件)的构建,就需要知道更多的Groovy知识。

3、比较Java和Groovy的语法

    用Groovy,你可以变得极其高效,同时代码量又少。

#############Java代码###############

package com.manning.gia;
public class ProjectVersion {
   private Integer major;
   private Integer minor;
   public ProjectVersion(Integer major, Integer minor) {
      this.major = major;
      this.minor = minor;
   }

    // 省略了getter、setter方法

}

###############Groovy代码###########

package com.manning.gia
class ProjectVersion {
   Integer major
   Integer minor
   ProjectVersion(Integer major, Integer minor) {
      this.major = major
      this.minor = minor
   }
}

Groovy对你写的类假设了一些合理的默认值,特别是一下一些优化:

(1)表达式末尾的分号不是必需的

(2)每个类、构造器以及方法默认都是public

(3)方法体的最后一条表达式会作为返回值,意味着return语句也是可选的

(4)Groovy编译器会自动添加 getter/setter 方法

(5)类的字段(也叫properties)可以用 点 来访问,但实际上在背后调用了自动生成的getter/setter方法,你还以为这不就是好像public一样吗

(6)如果你用 == 来比较一个类的2个实例,Groovy背后自动调用 equals。

4、基本的Groovy特性

    有2个工具极其有用,可以运行代码。(1)Groovy console,它提供了一个交互式用户界面可以输入并执行Groovy脚本。可以运行groovyConsole或<GROOVY_HOME>/bin里的groovyConsole.bat来启动它。

(2)Groovy web console

4.1 Assert语句

    如果你来自Java,你可能知道assert这个关键字。它用于检验前置和后置条件。不过,Java中,你要开启assertion checking(通过设置运行时标识-ea或-enableassertion),这个特性才能用。Groovy的总是可用的。

def version = 12
assert version == 12
version++
assert version == 12

4.2 可选的数据类型声明

    Groovy不会强制要你显式声明变量、方法参数或返回值的类型。关键字def是java.lang.Object的占位符,Groovy会根据赋的值来判断类型。

def buildTool = 'Gradle'

assert buildTool.class == java.lang.String

def initProjectVersion(major, minor) {

    new ProjectVersion(major, minor)

}

assert initProjectVersion(1, 2).class == com.manning.gia.ProjectVersion

    但是你也许仍然更倾向于显式、强类型。特别是在那些暴露公共API的项目中,强类型使得要提供什么类型的参数更显而易见,对IDE代码补全也有用。如果一个方法没有返回值,那用void而不是def作为返回类型。

4.3 可选的括号

    如果方法签名要求至少一个参数,则方法调用可以省略括号。

initProjectVersion(1, 2)
initProjectVersion 1, 2
println('Groovy is awesome!')
println 'Groovy is awesome!'

4.4 Strings

    Groovy中声明Strings有3种办法。

def myString1 = 'This is a single-quoted String'
def myString2 = "This is a double-quoted String"
def myString3 = """
   This
   is a
   multiline
   String
"""

4.5 Groovy Strings(GStrings)

    Groovy中双引号括起来的字符串比传统的Java字符串更强大。插值变量或表达式。带这个的字符串叫GStrings。

def language = 'groovy'
def sentence = "$language is awesome!"
assert sentence == 'groovy is awesome!'
def improvedSentence = "${language.capitalize()} is awesome!"
assert improvedSentence == 'Groovy is awesome!'

4.6 Collections API

    Groovy为集合API的实现提供了简洁的语法,比Java的更易用。

【LISTS】

    方括号里放一些用逗号隔开的值就初始化了一个List。背后,Groovy创建了java.util.ArrayList的一个实例。操作符 << 可以将一个新元素添加到List中。背后,Groovy调用了add方法。

【MAPS】

    Maps处理起来比Lists容易。在方括号中放一个逗号分隔的键值对就初始化了一个Map。它的默认实现是java.lang.LinkedHashMap。

def inceptionYears = ['Ant': 2000, 'Maven': 2004]
assert inceptionYears.getClass() == java.lang.LinkedHashMap
assert inceptionYears.size() == 2
assert inceptionYears.Ant == 2000
assert inceptionYears['Ant'] == 2000

inceptionYears['Gradle'] = 2009
assert inceptionYears.size() == 3
assert inceptionYears['Gradle'] == 2009

inceptionYears.each { buildTool, year ->                 
   println "$buildTool was first released in $year"
}

4.7 Named parameters

    假设没有定义构造器,Groovy提供了另一种便捷的设置属性值的办法,叫 named parameters。该机制先调用该类的默认构造器,然后再为每一个提供的参数调用对应的setter方法。

class ProjectVersion {
   Integer major
   Integer minor
}

ProjectVersion projectVersion = new ProjectVersion(major: 1, minor: 10)

assert projectVersion.minor == 10
projectVersion.minor = 30
assert projectVersion.minor == 30

。。。。。。。。。。。。。。。。。。。。。。。。未完。。。。。。。。。。。

猜你喜欢

转载自zsjg13.iteye.com/blog/2248127