Markdown版本笔记 | 个人GitHub首页 | 个人博客 | 个人微信 | 个人邮箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
Gradle Groovy 基础语法 MDhtml
Gradle是目前Android主流的构建工具,无论你是经过命令行仍是经过AndroidStudio来build,最终都是经过Gradle来实现的。因此学习Gradle很是重要。git
目前国内对Android领域的探索已经愈来愈深,很多技术领域如插件化、热修复、构建系统
等都对Gradle有迫切的需求,不懂Gradle将没法完成上述事情。因此Gradle必需要学习。github
Gradle不仅仅是一个配置脚本,它的背后是几门语言:api
DSL的全称是
Domain Specific Language
,即领域特定语言,或者直接翻译成“特定领域的语言”,再直接点,其实就是这个语言不通用,只能用于特定的某个领域,俗称“小语言”。所以DSL也是语言。微信
实际上,Gradle脚本大多都是使用groovy语言编写的。闭包
Groovy是一门jvm语言,功能比较强大,细节也不少,所有学习的话比较耗时,对咱们来讲收益较小,而且玩转Gradle并不须要学习Groovy的所有细节,因此其实咱们只须要学一些Groovy基础语法与API便可。app
Groovy是一种基于JVM的敏捷开发语言,它结合了众多脚本语言的强大的特性,因为同时又能与Java代码很好的结合。一句话:既有面向对象的特性又有纯粹的脚本语言的特性。jvm
因为Groovy运行在JVM上,所以也可使用Java语言编写的组建。ide
简单来讲,Groovy提供了更加灵活简单的语法
,大量的语法糖
以及闭包
特性可让你用更少的代码来实现和Java一样的功能
。
Groovy是一门jvm语言,它最终是要编译成class文件而后在jvm上执行,因此Java语言的特性Groovy都支持
,Groovy支持99%的java语法,咱们彻底能够在Groovy代码中直接粘贴java代码。
能够安装Groovy sdk
来编译和运行。可是我并不想搞那么麻烦,毕竟咱们的最终目的只是学习Gradle。
推荐你们经过这种方式来编译和运行Groovy。
在当面目录下建立build.gradle
文件,在里面建立一个task
,而后在task中编写Groovy代码便可,以下所示:
task(testGroovy).doLast { println "开始运行自定义task" test() } def test() { println "执行Groovy语法的代码" System.out.println("执行Java语法的代码!"); }
而后在命令行终端中执行以下命令便可:
gradle testGroovy
> Configure project :app > Task :app:testGroovy 开始运行自定义task 执行Groovy语法的代码 执行Java语法的代码! BUILD SUCCESSFUL in 3s 1 actionable task: 1 executed
咱们知道,在Android项目中,咱们只要更改build.gradle
文件一点内容,AS就会提示咱们同步:
可是在咱们测试 Groovy 时中,咱们更改build.gradle
文件后能够没必要去同步,执行命令时会自动执行你修改后的最新逻辑。
Groovy中的类和方法默认都是public权限的,因此咱们能够省略public关键字,除非咱们想使用private。
Groovy中的类型是弱化的,全部的类型均可以动态推断
,可是Groovy仍然是强类型的语言
,类型不匹配仍然会报错。
Groovy中经过 def
关键字来声明变量和方法
。
Groovy中不少东西都是能够省略的,好比
省略return关键字并非一个好的习惯,就如同 if else while 后面只有一行语句时能够省略大括号同样,之后若是添加了其余语句,颇有可能会致使逻辑错误
def int a = 1; //若是 def 和 类型同时存在,IDE 会提示你"def是不须要的(is unnecessary)" def String b = "hello world" //省略分号,存在分号时也会提示你 unnecessary def c = 1 //省略类型 def hello() { //省略方法声明中的返回值类型 println ("hello world"); println "hello groovy" //省略方法调用时的圆括号 return 1; } def hello(String msg) { println "hello" + msg //省略方法调用时的圆括号 1; //省略return } int hello(msg) { //省略方法声明中的参数类型 println msg return 1 // 这个return不能省略 println "done" //这一行代码是执行不到的,IDE 会提示你 Unreachable statement,但语法没错 }
在Groovy中,数据类型有:
Closure(闭包)
类型能够显示声明,也能够用 def 来声明,用 def 声明的类型Groovy将会进行类型推断。
基本数据类型和对象和Java中的一致,只不过在Gradle中,对象默认的修饰符为public
。
String的特点在于字符串的拼接,好比
def a = 1 def b = "hello" def c = "a=${a}, b=${b}" println c //a=1, b=hello
Groovy中有一种特殊的类型,叫作Closure
,翻译过来就是闭包,这是一种相似于C语言中函数指针
的东西。
闭包用起来很是方便,在Groovy中,闭包做为一种特殊的数据类型
而存在,闭包能够做为方法的参数和返回值,也能够做为一个变量而存在
。
闭包能够有返回值和参数
,固然也能够没有。下面是几个具体的例子:
def test() { def closure = { String parameters -> //闭包的基本格式 println parameters } def closure2 = { a, b -> // 省略了闭包的参数类型 println "a=${a}, b=${b}" } def closure3 = { a -> a + 1 //省略了return } def closure4 = { // 省略了闭包的参数声明 println "参数为 ${it}" //若是闭包不指定参数,那么它会有一个隐含的参数 it } closure("包青天") //包青天 closure2 10086, "包青天" //a=10086, b=包青天 println closure3(1) //2 //println closure3 2 //不容许省略圆括号,会提示:Cannot get property '1' on null object closure4() //参数为 null closure4 //不容许省略圆括号,可是并不会报错 closure4 10086 //参数为 10086 }
闭包的一个难题是如何肯定闭包的参数(包括参数的个数、参数的类型、参数的意义),尤为当咱们调用Groovy的API时,这个时候没有其余办法,只有查询Groovy的文档才能知道。
Groovy增强了Java中的集合类,好比List、Map、Set等。
基本使用以下:
def emptyList = [] def list = [10086, "hello", true] list[1] = "world" assert list[1] == "world" println list[0] //10086 list << 5 //至关于 add() assert 5 in list // 调用包含方法 println list //[10086, world, true, 5]
def range = 1..5 assert 2 in range println range //1..5 println range.size() //5
def emptyMap = [:] def map = ["id": 1, "name": "包青天"] map << [age: 29] //添加元素 map["id"] = 10086 //访问元素方式一 map.name = "哈哈" //访问元素方式二,这种方式最简单 println map //{id=10086, name=哈哈, age=29}
能够看到,经过Groovy来操做List和Map显然比Java简单的多。
上面有一个看起来很奇怪的操做符<<
,其实这并无什么大不了,<<
表示向List中添加新元素
的意思,这一点从 List文档 当也能查到。
public List leftShift(Object value)
左移位运算符
,以提供将对象append
到List的简单方法。实际上,这个运算符是大量使用的,而且当你用 leftShift
方法时 IDE 也会提示你让你使用左移位
运算符<<
替换:
def list = [1, 2] list.leftShift 3 assert list == [1, 2, 3] list << 4 println list //[1, 2, 3, 4]
这里借助Map再讲述下如何肯定闭包的参数。好比咱们想遍历一个Map,咱们想采用Groovy的方式,经过查看文档,发现它有以下两个方法,看起来和遍历有关:
Map each(Closure closure)
:Allows a Map to be iterated through using a closure.Map eachWithIndex(Closure closure)
:Allows a Map to be iterated through using a closure.能够发现,这两个each方法的参数都是一个闭包,那么咱们如何知道闭包的参数呢?固然不能靠猜,仍是要查文档。
public Map each(Closure closure)
one parameter
then it will be passed the Map.Entry
otherwise if the closure takes two parameters
then it will be passed the key and the value
.TreeMap
will have its contents processed according to the natural ordering(天然顺序) of the map.def result = "" [a:1, b:3].each { key, value -> result += "$key$value" } //两个参数 assert result == "a1b3"
def result = "" [a:1, b:3].each { entry -> result += entry } //一个参数 assert result == "a=1b=3" [a: 1, b: 3].each { println "[${it.key} : ${it.value}]" } //一个隐含的参数 it,key 和 value 是属性名
试想一下,若是你不知道查文档,你又怎么知道each方法如何使用呢?光靠从网上搜,API文档中那么多接口,搜的过来吗?记得住吗?
在Groovy中,文件访问要比Java简单的多,不论是普通文件仍是xml文件。怎么使用呢?查来 File文档。
public Object eachLine(Closure closure)
能够看到,eachLine方法也是支持1个或2个参数的,这两个参数分别是什么意思,就须要咱们学会读文档了,一味地从网上搜例子,多累啊,并且很难完全掌握:
def file = new File("a.txt") file.eachLine { line, lineNo -> println "${lineNo} ${line}" //行号,内容 } file.eachLine { line -> println "${line}" //内容 }
除了eachLine,File还提供了不少Java所没有的方法,你们须要浏览下大概有哪些方法,而后须要用的时候再去查就好了,这就是学习Groovy的正道。
Groovy访问xml有两个类:XmlParser
和XmlSlurper
,两者几乎同样,在性能上有细微的差异,不过这对于本文不重要。
groovy.util.XmlParser
的 API文档
文档中的案例:
def xml = '<root><one a1="uno!"/><two>Some text!</two></root>' //或者 def xml = new XmlParser().parse(new File("filePath.xml")) def rootNode = new XmlParser().parseText(xml) //根节点 assert rootNode.name() == 'root' //根节点的名称 assert rootNode.one[0].@a1 == 'uno!' //根节点中的子节点 one 的 a1 属性的值 assert rootNode.two.text() == 'Some text!' //根节点中的子节点 two 的内容 rootNode.children().each { assert it.name() in ['one','two'] }
更多的细节查文档便可。
当你在Groovy中建立一个beans的时候,一般咱们称为POGOS(Plain Old Groovy Objects),Groovy会自动帮咱们建立getter/setter
方法。
当你对getter/setter
方法有特殊要求,你尽可提供本身的方法,Groovy默认的getter/setter
方法会被替换。
有一个bean
class Server { String name Cluster cluster }
初始化一个实例的时候你可能会这样写:
def server = new Server() server.name = "Obelix" server.cluster = aCluster
其实你能够用带命名的参数的默认构造器,会大大减小代码量:
def server = new Server(name: "Obelix", cluster: aCluster)
在Groovy中Class类型的.class
后缀不是必须的,好比:
def func(Class clazz) { println clazz } func(File.class) //class java.io.File func(File) //class java.io.File
当更新一个实例的时候,你可使用with()来省略相同的前缀,好比:
Book book = new Book() book.with { id = 1 //等价于 book.id = 1 name = "包青天" start(10086) stop("包青天") }
全部类型都能转成布尔值,好比null
和void
至关于0
或者至关于false
,其余则至关于true
,因此:
if (name) {} //等价于 if (name != null && name.length > 0) {}
在Groovy中能够在类中添加asBoolean()
方法来自定义是否为真
。
在Groovy中,三元表达式能够更加简洁,好比:
def result = name ?: "" //等价于 def result = name != null ? name : ""
若是你实在不想关心try
块里抛出何种异常,你能够简单的捕获全部异常,而且能够省略异常类型:
try { // ... } catch (any) { //能够省略异常类型 // something bad happens }
这里的any并不包括Throwable
,若是你真想捕获everything,你必须明确的标明你想捕获Throwable
在java中,你要获取某个对象的值必需要检查是否为null,这就形成了大量的if
语句;在Groovy中,非空判断能够用?.
表达式,好比:
println order?.customer?.address //等价于 if (order != null) { if (order.getCustomer() != null) { if (order.getCustomer().getAddress() != null) { System.out.println(order.getCustomer().getAddress()); } } }
在Groovy中,可使用assert来设置断言,当断言的条件为false时,程序将会抛出异常
:
def check(String name) { assert name // 检查方法传入的参数是否为空,name non-null and non-empty according to Groovy Truth assert name?.size() > 3 }
Groovy里的is()
方法等同于Java里的==
。
Groovy中的==
是更智能的equals()
,比较两个类的时候,你应该使用a.is(b)
而不是==
。
Groovy中的==
能够自动避免NullPointerException异常
status == "包青天" //等价于Java中的 status != null && status.equals("包青天")
在Groovy中,switch方法变得更加灵活,能够同时支持更多的参数类型:
def x = null def result = "" switch (x) { case "foo": result = "found foo" //没有 break 时会继续向下判断 case "bar": result += "bar" break case [4, 5, 6]: result = "list" //匹配集合中的元素 break case 12..30: result = "range" //匹配某个范围内的元素 break case Integer: result = "integer" //匹配Integer类型 break case { it > 3 }: result = "number > 3" //匹配表达式 break case Number: result = "number" //匹配Number类型 break default: result = "default" } println result
Java中,字符串过长须要换行时咱们通常会这样写:
throw new PluginException("Failed to execute command list-applications:" + " The group with name " + parameterMap.groupname[0] + " is not compatible group of type " + SERVER_TYPE_NAME)
Groovy中你能够用 \
字符,而不须要添加一堆的双引号:
throw new PluginException("Failed to execute command list-applications: \ The group with name ${parameterMap.groupname[0]} \ is not compatible group of type ${SERVER_TYPE_NAME}")
或者使用多行字符串"""
:
throw new PluginException("""Failed to execute command list-applications: The group with name ${parameterMap.groupname[0]} is not compatible group of type ${SERVER_TYPE_NAME)}""")
Groovy中,单引号
引发来的字符串是java字符串,不能使用占位符来替换变量,双引号
引发的字符串则是java字符串或者Groovy字符串。
在java中使用两个类名相同但包名不一样的两个类,像java.util.List
和java.wt.List
,你必须使用完整的包名才能区分。Groovy中则可使用import别名:
import java.util.List as jurist //使用别名 import java.awt.List as aList import java.awt.WindowConstants as WC import static pkg.SomeClass.foo //静态引入方法
2019-1-12