Gradle系列之Groovy基础篇
原文发于微信公众号 jzman-blog,欢迎关注交流。
上一篇学习了 Gradle 的入门知识,Gradle 基于 Groovy,今天学习一下 Groovy 的基础知识,Groovy 是基于 JVM 虚拟机的一种动态语言,语法与 Java 语法类似,Groovy 完全兼容 Java,每个 Gradle 文件都是一个 Groovy 脚本文件,Gradle 文件基于 Groovy 语法,而 Groovy 又兼容 Java,故可以在 Gradle 文件中写 Java 代码,在此基础上增加了很多新特性,如支持闭包、DSL等,可以说 Groovy 是一门非常灵活的动态脚本语言,阅读本文之前可以先阅读下面这篇文章:
下面针对 Gradle 来学习一下 Groovy 的一些基础知识。
- 字符串
- 集合
- 方法
- JavaBean
- 关于闭包
字符串
说一个 Groovy 的特性,在 Groovy 中分号不是必须的,其单引号是双引号都定义的是一个字符串常量,不同之处是单引号是纯粹的字符串常量,不会对该字符串里面的表达式做运算,而使用双引号定义的字符串常量可以使用合法表达式做相关运算,测试代码如下:
task stringTest{
//使用def关键字定义变量,
def str1 = "双引号"
def str2 = '单引号'
println "双引号定义的字符串:"+str1
println "双引号定义的字符串:"+str1.class
println "单引号定义的字符串:"+str2
//变量动态变化
str1 = true;
println "双引号定义的字符串:"+str1.class
//使用$运算符
println "双引号定义的字符串:${str1}"
//只有一个变量的时候可以省去中括号
println "双引号定义的字符串:$str1"
//单引号定义的字符串不能使用表达式进行运算
println '单引号定义的字符串:$str2'
}
下面是执行结果,参考如下:
PS E:\Gradle\study\Groovy> gradle stringTest
> Configure project :
双引号定义的字符串:双引号
双引号定义的字符串:class java.lang.String
单引号定义的字符串:单引号
双引号定义的字符串:class java.lang.Boolean
双引号定义的字符串:true
双引号定义的字符串:true
单引号定义的字符串:$str2
BUILD SUCCESSFUL in 1s
集合
Groovy 中也有集合的概念,主要看一下常用的 List、Map,下面将对 List 和 Map 常用操作进行介绍。
那么如何在 Groovy 中定义 List 呢,Groovy 中的 List 的定义方式类似于 Java 中的数组,具体操作参考下面代码:
task list{
//定义List
def list = [1,2,3,4,5,6];
def weekList = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日'];
println "list的类型:"+list.class
println "weekList的类型:"+weekList.class
//访问集合里面的元素
println '第一个元素:'+list[0]//访问第一个元素
println '第二个元素:'+list[1]//访问第二个元素,以此类推
println '最后一个元素:'+list[-1]//访问最后一个元素
println '倒数第二个元素:'+list[-2]//访问倒数第二个元素,以此类推
println '某个范围内元素:'+list[2..4]//访问某个范围内元素,以此类推
//使用each遍历集合中的元素
weekList.each{
//使用it作为迭代的元素变量,不能写错喔
println it
}
}
下面是上述代码的执行结果,参考如下:
PS E:\Gradle\study\Groovy\ListMap> gradle list
> Configure project :
list的类型:class java.util.ArrayList
weekList的类型:class java.util.ArrayList
第一个元素:1
第二个元素:2
最后一个元素:6
倒数第二个元素:5
某个范围内元素:[3, 4, 5]
星期一
星期二
星期三
星期四
星期五
星期六
星期日
BUILD SUCCESSFUL in 2s
那么如何在 Groovy 中定义 Map 呢,Groovy 中的 Map 当然也是键值对,具体定义及操作参考下面代码:
task map{
//定义Map
def map = ['name':'Groovy', 'age':10];
println "map的类型:"+map.getClass().name;
//访问Map里面的元素
println map.name;
println map['name'];
//遍历Map中的元素
map.each{
println "Key:${it.key},value:${it.value}"
}
}
下面是上述代码的执行结果,参考如下:
PS E:\Gradle\study\Groovy\ListMap> gradle map
> Configure project :
map的类型:java.util.LinkedHashMap
Groovy
Groovy
Key:name,value:Groovy
Key:age,value:10
BUILD SUCCESSFUL in 2s
关于 Groovy 的集合就了解这么多。
方法
Groovy 中的方法和 Java 中的方法类似,只是写法上更加灵活,Groovy 中 return 不是必须的,在不写 return 的时候,Groovy 会将最后一句代码作为该方法的返回值。代码块指的是一段被花括号包围的代码,Groovy 中可将代码块作为一个参数进行传递,可以参考前面关于集合的遍历部分,参考代码如下:
task method{
//方法调用
methodA(1, 2)
methodA 1, 2
//获取方法返回的结果
def a = methodA 10, 20
println '获取方法返回的结果:'+a
//代码块作为参数传递
def list = [1,2,3,4,5];
list.each(
//闭包参数
{
// println it
}
)
//Groovy规定,如果方法的最后一个参数是闭包,可以直接放到方法外面
list.each(){
// println it
}
//简写方式
list.each{
println it
}
}
//方法的定义
def methodA(int a, int b){
println a + b
//Groovy中return语句不是必须的,默认将最后一句代码的结果作为返回值
a + b
}
下面是上述代码参考如下:
PS E:\Gradle\study\Groovy\Method> gradle method
> Configure project :
3
3
30
获取方法返回的结果:30
1
2
3
4
5
BUILD SUCCESSFUL in 2s
JavaBean
Groovy 中的 JavaBean 相较 Java 中的比较灵活,可以直接使用 javaBean.属性的方式获取和修改 JavaBean 的属性值,无需使用相应的 Getter、Setter 方法,直接看代码:
task javaBean{
//Groovy中定义JavaBean
Student student = new Student()
student.name = "Groovy"
student.age = 10
student.setName("Gradle")
println "名字是:"+student.name
//不能调用Getter方法获取值
// println "名字是:"+student.getName
println "年龄是:${student.age}"
println "分数是:"+student.score
}
class Student{
private String name
private int age
//定义的Getter方法所对应的属性可以直接调用
public String getScore(){
100
}
//属性的Getter、Setter方法
public String setName(String name){
this.name = name
}
public void getName(){
name
}
}
下面是上述代码的执行结果:
PS E:\Gradle\study\Groovy\JavaBean> gradle javaBean
> Configure project :
名字是:Gradle
年龄是:10
分数是:100
BUILD SUCCESSFUL in 2s
闭包
闭包是大多数脚本语言具有的一个特性,如 JavaScript、Groovy 等,闭包就是一个使用花括号包围的代码块,下面来学习 Groovy 中的闭包,主要有两部分:闭包及闭包参数传递和闭包委托。
闭包及其参数传递
下面来看一下如何定义一个闭包以及相关参数的传递,直接上代码:
task closure{
//自定义闭包的执行
mEach{
println it
}
//向闭包传递参数
mEachWithParams{m,n -> //m,n ->将闭包的参数和主体区分离开来
println "${m} is ${n}"
}
}
//1.定义一个方法,参数closure用于接收闭包
//2.闭包的执行就是花括号里面代码的执行
//3.闭包接收的参数就是闭包参数closure参数中的i,如果是一个参数默认就是it变量
def mEach(closure){
for(int i in 1..5){
closure(i)
}
}
//向闭包传递参数
def mEachWithParams(closure){
def map = ["name":"Groovy","age":10]
map.each{
closure(it.key, it.value)
}
}
上面代码中定义了闭包以及如何进行闭包的参数的传递,当闭包只有一个参数时,默认就是 it,反之闭包有多个参数时,就需要将参数定义出来,具体可参考上述代码,下面是执行结果:
PS E:\Gradle\study\Groovy\Closure> gradle delegate
> Configure project :
1
2
3
4
5
name is Groovy
age is 10
BUILD SUCCESSFUL in 2s
闭包委托
Groovy 闭包的强大之处在于它支持闭包方法的委托,Groovy 的闭包有三个属性:thisObject、owner、delegate,当在一个闭包中调用定义的方法时,由这三个属性来确定该方法由哪个对象来执行,默认 owner 和 delegate 是相等的,其中 delete 是可以被修改的,Gradle 中闭包的很多功能都是通过修改 delegate 来实现的。下面通过定义一个闭包以及方法,通过打印来说明这三个属性的一些区别:
//闭包的委托
task delegate{
new Delegate().test{
//Groovy闭包的三个属性:thisObject、owner、delegate
println "thisObject:${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
//闭包默认it
println "闭包默认it:"+it.getClass()
//定义的方法,优先使用thisObject来处理
method()
//闭包中的方法
it.method()
}
}
def method(){
println "mththod in root:${this.getClass()}"
}
class Delegate{
def method(){
println "mththod in Delegate:${this.getClass()}"
}
//闭包
def test(Closure<Delegate> closure){
closure(this);
}
}
下面是上述代码的执行结果,参考如下:
PS E:\Gradle\study\Groovy\Closure> gradle delegate
> Configure project :
thisObject:class build_3ajca04o1rprxygcsq0ajvt7i
owner:class build_3ajca04o1rprxygcsq0ajvt7i$_run_closure2
delegate:class build_3ajca04o1rprxygcsq0ajvt7i$_run_closure2
闭包默认it:class Delegate
mththod in root:class build_3ajca04o1rprxygcsq0ajvt7i
mththod in Delegate:class Delegate
BUILD SUCCESSFUL in 2s
当在闭包中调用方法 method() 时,发现是 thisObject 调用了 method() 方法,而不是 owner 或 delegate,说明闭包中优先使用 thisObject 来处理方法的执行,同时可以看到 owner 和 delegate 是一致的,但是 owner 比 delegate 的优先级要高,所以闭包中方法的处理顺序是:thisObject > owner > delegate。
Gradle 中一般会指定 delegate 为当前的 it,这样我们将可以通过 delegate 指定的对象来操作 it 了,下面指定闭包的 delegate 并设置委托优先,让委托的具体对象来执行其方法,下面是测试代码:
task student{
configStudent{
println "当前it:${it}"
name = "Groovy"
age = 10
getInfo()
}
}
class Student{
String name
int age
def getInfo(){
println "name is ${name}, age is ${age}"
}
}
def configStudent(Closure<Student> closure){
Student student = new Student()
//设置委托对象为当前创建的Student实例
closure.delegate = student
//设置委托模式优先,如果不设置闭包内方法的处理者是thisObject
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
//设置it变量
closure(student)
}
下面是上述代码的执行结果,参考如下:
PS E:\Gradle\study\Groovy\Closure> gradle student
> Configure project :
当前it:Student@18f6d755
name is Groovy, age is 10
BUILD SUCCESSFUL in 2s
总结
学习 Groovy 的目的还是为了加深对 Gradle 构建工具的理解,上面通过五个方面对 Groovy 有了初步的人认识,后续如果有需要在看 Groovy 的高级用法。
如果感兴趣,可以关注公众号:躬行之(jzman-blog),一起交流学习。
Gradle系列之Groovy基础篇的更多相关文章
- 手摸手,带你用Beego撸商城系列一(基础篇)
完整项目地址: go-shop-b2c 系列文章: 手摸手,带你用 Beego撸商城 系列一(基础篇) 手摸手,带你用 Beego撸商城 系列二(登录篇) 手摸手,带你用 Beego撸商城 系列三(系 ...
- Gradle+Groovy基础篇
在Java项目中,有两个主要的构建系统:Gradle和Maven.构建系统主要管理潜在的复杂依赖关系并正确编译项目.还可以将已编译的项目以及所有资源和源文件打包到.war或.jar文件中.对于简单的构 ...
- Gradle系列之一 Groovy语法精讲
Gradle技术之一 Groovy语法精讲 gradle脚本是基于groovy语言开发的,想要学好gradle必须先要对groovy有一个基本的认识 1. Groovy特点 groovy是一种DSL语 ...
- [Android 性能优化系列]内存之基础篇--Android怎样管理内存
大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...
- 探索ASP.NET MVC5系列之~~~1.基础篇---必须知道的小技能
其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程 汇总:http://www.cnblogs.com/dunitian/p/4822808.html#mvc 本章D ...
- asp.net core 系列之中间件基础篇(middleware)
中间件是一种插入到管道上进行处理请求和响应的软件:每个中间件组件具有下面的功能: 选择是否把请求传递到管道上的下一个组件 可以在下一个组件的之前和之后做处理工作 请求委托(request delega ...
- Gradle系列之构建脚本基础
原文发于微信公众号 jzman-blog,欢迎关注交流. 前面两篇文章分别介绍了 Gradle 基础知识以及 Groovy 相关基础知识,这也是学习 Gradle 所必需了解的,文章链接如下:: Gr ...
- Gradle系列之Android Gradle基础配置
原文发于微信公众号 jzman-blog,欢迎关注交流. 通过前面几篇文章学习了 Gradle 基础知识以及 Gradle 插件相关的知识,关于 Gradle 及其插件相关知识请先阅读下面几篇文章: ...
- SQL系列总结——基础篇(一)
数据库与表.列的关系其实就像是一个Excel工作薄(workbook)与Excel表格(sheet)以及表格中的列的关系一样.关系数据库中最基本的对象有3个:表.列.用户 基本的概念名词 ...
随机推荐
- 洛谷P1003 铺地毯 模拟
这一题就是一个很普通的模拟,每次输入的时候存储四个角的值 把四个角的横纵坐标存储在一排.然后在倒序遍历一遍,查找的时候就看所要查找的坐标在不在这个范围内,如果找到了就标记一下再输出,如果没有找到就输出 ...
- shell脚本基础知识以及变量
一.基础知识 1.shell脚本的格式注意事项 第一行(一般必须写明):指定脚本使用的shell(若不写明也不影响脚本的执行,系统会自动以sh解析脚本)."#!/bin/bash" ...
- OpenCV-Python教程简介 | 一
OpenCV OpenCV由Gary Bradsky于1999年在英特尔创立,第一版于2000年问世.Vadim Pisarevsky加入Gary Bradsky,一起管理英特尔的俄罗斯软件OpenC ...
- w3cshool -- 排列组合去重算法挑战
function permAlone(str) { if(str.length == 1) return str; var a = str.substr(0, 1), one = [a], count ...
- Java 垃圾回收机制方法,判断对象存活算法
垃圾回收机制: 不定时去堆内存中清理不可达对象.不可达的对象并不会马上就会直接回收, 垃圾收集器在一个Java程序中的执行是自动的,不能强制执行,即使程序员能明确地判断出有一块内存已经无用了,是应该回 ...
- Spring中应用的那些设计模式
设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆. 今天,我们就设计模式的内在价值做一番探讨,并以spring为例进行讲解,只有领略了其设计的思想理念 ...
- 如何在Vue中优雅的使用防抖节流
1. 什么是防抖节流 防抖:防止重复点击触发事件 首先啥是抖? 抖就是一哆嗦!原本点一下,现在点了3下!不知道老铁脑子是不是很有画面感!哈哈哈哈哈哈 典型应用就是防止用户多次重复点击请求数据. 代码实 ...
- stdio.h file not found mac catalina clion 头文件 找不到
问题:mac update catalina 版本之后引发的include文件问题 近期Mac 版本升级到catalina版本,使用CLion调试c/c++程序,莫名其妙的发现,有些头文件incl ...
- django-生产和测试环境分离
django-生产和测试环境分离 在settings.py的同级目录下新建settings的文件夹 在settings文件夹下新建 __init__.py base.py develop.py pro ...
- 文件的读写 - open
#写文件,r路径\n 空格\t 缩进# fan=open(r'C:/Users/demiyangping_v/Desktop/fan.txt','w', encoding='utf-8')# fan. ...