Gradle Groovy 基础语法 MD
Markdown版本笔记 | 我的GitHub首页 | 我的博客 | 我的微信 | 我的邮箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
Gradle Groovy 基础语法 MD
目录
Groovy 基础
为何要学 Groovy
为何要使用 Groovy
如何编译运行 Groovy
最基本的语法
支持的数据类型
String
闭包
List和Map
闭包的参数
加强的IO
访问xml文件
其他的一些语法特性
Getter和Setter
构造器
Class类型
使用with()操作符
判断是否为真
简洁的三元表达式
捕获任何异常
简洁的非空判断
使用断言
==和equals
switch方法
字符串分行
Import 别名
Groovy 基础
为何要学 Groovy
Gradle是目前Android主流的构建工具,不管你是通过命令行还是通过AndroidStudio来build,最终都是通过Gradle来实现的。所以学习Gradle非常重要。
目前国内对Android领域的探索已经越来越深,不少技术领域如插件化、热修复、构建系统
等都对Gradle有迫切的需求,不懂Gradle将无法完成上述事情。所以Gradle必须要学习。
Gradle不单单是一个配置脚本,它的背后是几门语言:
- Groovy Language
- Gradle DSL
- Android DSL
DSL的全称是
Domain Specific Language
,即领域特定语言,或者直接翻译成“特定领域的语言”,再直接点,其实就是这个语言不通用,只能用于特定的某个领域,俗称“小语言”。因此DSL也是语言。
实际上,Gradle脚本大多都是使用groovy语言编写的。
Groovy是一门jvm语言,功能比较强大,细节也很多,全部学习的话比较耗时,对我们来说收益较小,并且玩转Gradle并不需要学习Groovy的全部细节,所以其实我们只需要学一些Groovy基础语法与API即可。
为何要使用 Groovy
Groovy是一种基于JVM的敏捷开发语言,它结合了众多脚本语言的强大的特性,由于同时又能与Java代码很好的结合。一句话:既有面向对象的特性又有纯粹的脚本语言的特性。
由于Groovy运行在JVM上,因此也可以使用Java语言编写的组建。
简单来说,Groovy提供了更加灵活简单的语法
,大量的语法糖
以及闭包
特性可以让你用更少的代码来实现和Java同样的功能
。
如何编译运行 Groovy
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中很多东西都是可以省略的,比如
- 语句后面的分号是可以省略的
- def 和 变量的类型 中的其中之一是可以省略的(不能全部省略)
- def 和 方法的返回值类型 中的其中之一是可以省略的(不能全部省略)
- 方法调用时的圆括号是可以省略的
- 方法声明中的参数类型是可以省略的
- 方法的最后一句表达式可作为返回值返回,而不需要return关键字
省略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中,数据类型有:
- Java中的基本数据类型
- Java中的对象
Closure(闭包)
- 加强的List、Map等集合类型
- 加强的File、Stream等IO类型
类型可以显示声明,也可以用 def 来声明,用 def 声明的类型Groovy将会进行类型推断。
基本数据类型和对象和Java中的一致,只不过在Gradle中,对象默认的修饰符为public
。
String
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的文档才能知道。
List和Map
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)
- Overloads the left shift operator to provide an easy way to append objects to a List. 重载
左移位运算符
,以提供将对象append
到List的简单方法。 - Parameters: value - an Object to be added to the List.
- Returns: same List, after the value was added to it.
实际上,这个运算符是大量使用的,并且当你用 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)
- Allows a Map to be iterated through using a closure. If the closure takes
one parameter
then it will be passed theMap.Entry
otherwise if the closure takestwo parameters
then it will be passedthe key and the value
. - In general, the order in which the map contents are processed cannot be guaranteed(通常无法保证处理元素的顺序). In practise(在实践中), specialized forms of Map(特殊形式的Map), e.g. a
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文档中那么多接口,搜的过来吗?记得住吗?
加强的IO
在Groovy中,文件访问要比Java简单的多,不管是普通文件还是xml文件。怎么使用呢?查来 File文档。
public Object eachLine(Closure closure)
- Iterates through this file line by line. Each line is passed to the given 1 or 2 arg closure. The file is read using a reader which is closed before this method returns.
- Parameters: closure - a closure (arg 1 is line, optional arg 2 is line number starting at line 1)
- Returns: the last value returned by the 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的正道。
访问xml文件
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'] }
更多的细节查文档即可。
其他的一些语法特性
Getter和Setter
当你在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)
Class类型
在Groovy中Class类型的.class
后缀不是必须的,比如:
def func(Class clazz) {
println clazz
}
func(File.class) //class java.io.File
func(File) //class java.io.File
使用with()操作符
当更新一个实例的时候,你可以使用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
}
==和equals
Groovy里的is()
方法等同于Java里的==
。
Groovy中的==
是更智能的equals()
,比较两个类的时候,你应该使用a.is(b)
而不是==
。
Groovy中的==
可以自动避免NullPointerException异常
status == "包青天"
//等价于Java中的
status != null && status.equals("包青天")
switch方法
在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字符串。
Import 别名
在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
Gradle Groovy 基础语法 MD的更多相关文章
- Groovy系列(3)- Groovy基础语法
Groovy基础语法 动态类型 Groovy定义变量时:可以用Groovy风格的def声明,不指定类型:也可以兼容Java风格,指定变量类型:甚至还可以省略def或类型 def t1 = 't1' S ...
- Groovy基础语法
Groovy 基础语法 变量定义 1.支持动态类型,使用def关键字定义变量 // Java中定义变量的方式 int age = 18; String name = "张三"; / ...
- Gradle+Groovy基础篇
在Java项目中,有两个主要的构建系统:Gradle和Maven.构建系统主要管理潜在的复杂依赖关系并正确编译项目.还可以将已编译的项目以及所有资源和源文件打包到.war或.jar文件中.对于简单的构 ...
- -Shell 教程 Bash 脚本 基础语法 MD
目录 目录 Shell 简介 Shell 脚本 Shell 环境 第一个shell脚本 Shell 变量 定义变量 使用变量 只读变量 删除变量 Shell 字符串 单引号 双引号 字符串基本操作 S ...
- groovy常用语法及实战
groovy语言简介 一种基于JVM的敏捷开发语言,作为编程语言可编译成java字节码,也可以作为脚本语言解释执行. 结合了Python.Ruby和Smalltalk的许多强大的特性 支持面向对象编程 ...
- 【Gradle】Groovy基础
Groovy基础 Groovy是基于JVM虚拟机的一种动态语言.每个Gradle的build脚本文件都是一个Groovy脚本文件. 字符串 在Groovy中,分号不是必需的.在Groovy中,单引号和 ...
- .md(markdown)基础语法
markdown基础语法笔记,方便翻看. 1. 标题 标题有3中写法,可混写: (1)# ***,前面#,后面文字,注意,#与文字间有空格,1-6个#分别表示h1-h6,h1.h2下有横线 (2)== ...
- gradle使用基础
说明 介绍gradle使用基础,gradle基础脚本结构和常规使用方法,以及一个简单的gradle示例.主要是为了简单的介绍gradle使用. gradle环境配置 gradle可以通过两种方式运行g ...
- Java基础语法
java基础学习总结——基础语法1 一.标识符
随机推荐
- VMware 使用本机代理上网
灰机使用方法 VMware 安装方法 首先解决主机的配置 1.查询本机 IP 地址,使用 ipconfig /all 2.更改小灰机的设置 3.虚拟机设置 4.Ubuntu 设置
- SQL Server Management Studio 教程二: 创建新登录名
1.先用windows身份登录SQL server2008 2.打开[安全性],右击[登录名],选择[新建登录名] 3.[常规]选项页面中,修改如下位置设置,默认数据库可以是其他数据库,不一定是mas ...
- SVN提示https证书验证失败问题svn: E230001: Server SSL certificate verification failed:
最近在使用Idea 检出 svn项目时,出现了如下的画面 显示需要授权证书,需要证书路径 搜索网上的解决方式:无非以下几种 1.File->Settings->Version Contro ...
- mysql_提示 Lock wait timeout exceeded解决办法
我的mysql报这个错 err=1205 - Lock wait timeout exceeded; try restarting transaction 利用 SHOW PROCESSLIST来查看 ...
- 使用 IntraWeb (10) - CSS
IW 会把大多数的视觉属性转换为 CSS; 我们主动使用 CSS 要分两步: 第一步: {通过窗体的 StyleSheet 属性指定要链接的 CSS 文件} procedure TIWForm1.IW ...
- 推荐13个.Net开源的网络爬虫
1:.Net开源的跨平台爬虫框架 DotnetSpider Star:430 DotnetSpider这是国人开源的一个跨平台.高性能.轻量级的爬虫软件,采用 C# 开发.目前是.Net开源爬虫最为优 ...
- CentOS 6.8 安装最新版 Git
CentOS 6.8 自带的 Git 版本为 1.7.1,比较旧,yum 安装也停留在 1.7.1,还是源码编译安装吧. 1. 下载源码: wget -c https://github.com/git ...
- tomcat点击startup.bat一闪而退的方法
摘要 在摸索tomcat的配置的时候,发现在启动tomcat服务器的时候,点击startup一闪而退. 解决办法 分析闪退原因,简单做法,右键编辑startup.bat文件,在最后一行添加“pause ...
- On premise TFS Git OAuth clone failed on agent
利用TFS2015的跨平台生成代理,在mac osx 上生成xamarin.ios项目,agent费劲九牛二虎之力搞定了(参见http://www.cnblogs.com/zjoch/p/581101 ...
- CLR如何加载程序集以及程序集版本策略
在项目的配置文件Web.config中,会看到<runtime>节点,以及包含在其中的<assemblyBinding>节点,这显然与程序集有关,这些节点到底何时被用到呢? 在 ...