zoukankan      html  css  js  c++  java
  • 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 的一些基础知识。

    1. 字符串
    2. 集合
    3. 方法
    4. JavaBean
    5. 关于闭包

    字符串

    说一个 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:GradlestudyGroovy> 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:GradlestudyGroovyListMap> 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:GradlestudyGroovyListMap> 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:GradlestudyGroovyMethod> 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:GradlestudyGroovyJavaBean> 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:GradlestudyGroovyClosure> 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:GradlestudyGroovyClosure> 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:GradlestudyGroovyClosure> gradle student
    
    > Configure project :
    
    当前it:Student@18f6d755
    name is Groovy, age is 10
    
    
    BUILD SUCCESSFUL in 2s
    

    总结

    学习 Groovy 的目的还是为了加深对 Gradle 构建工具的理解,上面通过五个方面对 Groovy 有了初步的人认识,后续如果有需要在看 Groovy 的高级用法。

    如果感兴趣,可以关注公众号:躬行之(jzman-blog),一起交流学习。

  • 相关阅读:
    elasticsearch插件开发
    elasticsearch启动流程
    HBase结构
    Scala统计一个文件所有单词出现的次数
    es基础知识
    Linux中Swap与Memory内存简单介绍
    linux 常用命令
    巅峰对决之Swarm、Kubernetes、Mesos
    【JS】JS知识小结
    【HTTP】HTTP状态码详解
  • 原文地址:https://www.cnblogs.com/jzmanu/p/12749245.html
Copyright © 2011-2022 走看看