github 代码在此
介绍部分
.1主流的构建工具
- Ant(Apache Ant)
软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于java环境中的软件开发 - Maven
从ant中借用了绝大多数构建任务,其突出的是依赖管理和项目发布 - Gradle
使用Groovy语言,构建脚本,不再像Maven一样使用xml
.2 Gradle介绍
一个开源的项目自动化构建工具,建立在Apache Ant和Apache Maven概念的基础上,并引入了基于Groovy的特定领域语言(DSL),而不再使用XML形式管理构建脚本。
.2.1 DSL(Domain Specific Language)
定义:针对某一领域,具有首先表达性的一种计算机程序设计语言。只针对一个领域做出来的简洁语言,而非为了通用设计。(MATLAB计算语言,UML建模语言,HTML浏览器可识别网页语言),Groovy主要用于做脚本。
1 Groovy语法
- Groovy是基于java虚拟机的一种敏捷的动态语言,它是一种成熟的OOP(面向对象)编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同事又具有闭包和动态语言中的其他特性。
- 结合了python、Ruby和SmallTalk的许多强大的特性
- groovy可以与java完美结合,可以使用已经存在的所有java类库
- 语法上支持动态类型,闭包等新一代语言特性
- 既支持面向对象编程也支持面向过程编程
- 既可以作为编程语言也可以作为脚本语言
- 没有访问权限控制,都是public的
1.1 变量
//不管声明基本类型还是对象类型,groovy所有类型都是对象类型
int x = 10;
println x.class //class java.lang.Integer
double y =3.14
println y.class //class java.lang.Double
1.1.1 def关键字的是用
//def 弱类型定义
//如果变量不会被外部使用,使用def声明,如果要被外部使用,定义为java方式强类型
def x_1 = 11
println(x_1.class)//class java.lang.Integer
def y_1 = 3.1415
println(y_1.class)//class java.math.BigDecimal
def name = "Android"
println(name.class)//class java.lang.String
// 使用def定义的类型是可变类型的,动态类型
x_1 = 'Test'
println(x_1.class)//class java.lang.String
1.1.2 字符串
①定义方式
//一个单引号,无格式字符串,需要字符串拼接,转义字符等指定格式
def name = 'a single string'
println name.class //class java.lang.String
//三个单引号
def thupleName = '''three single string'''
println thupleName.class //class java.lang.String
//三个单引号,直接指定格式,无需 + "" 拼接
def thupleName2 = '''line one
line two
line three
'''
println thupleName2
//双引号定义字符串 可扩展字符串
def doubleName = "this is a common String"
println(doubleName.class)//class java.lang.String
def name2 = "Android"
//如果是可扩展字符串,类型变为GString
def sayHello = "Hello:${name2}"
println( sayHello )//Hello:Android
println( sayHello.class ) // class org.codehaus.groovy.runtime.GStringImpl
def sum = "THE sum of 2 and 3 equals ${2+3}"//可扩展做任意的表达式
println(sum) //THE sum of 2 and 3 equals 5
//传入了GString 接收参数为String,无需像java一样转型
def result = echo(sum)
println(result)//class java.lang.String
println(result.class)//class java.lang.String
String echo(String messagse){
return messagse
}
②字符串方法
- java.lang.String的方法
- DefaultGroovyMethods
- StringGroovyMethods (继承于DefaultGroovyMethods),包括普通类型的参数和闭包类型的参数
def str = "groovy"
//填充
//center() 对字符串的填充
println(str.center(8,'a'))//agroovya 两边填充a
println str.padLeft(8,'a')//aagroovy 左边填充a
println str.padRight(8,'a')//groovyaa 右边填充a
//比较
def str2 = "Hello"
println str > str2//unicode 编码比较 true
//索引
println str[0]//g
println str[0..1]//gr
//减法
def str3 = "Hello groovy"
println str3.minus(str2)//groovy
//等同于'-'操作符
println str3 - str2
//逆向操作
println str.reverse()
//首字母大写
println str.capitalize()
//判断是否是数字类型的字符串
println str.isNumber()
//转化类型
def strBoolean = '1'
println strBoolean.toBoolean()//true
def strLong = '1'
println strLong.isLong()
strLong.toLong()
def strDouble = '1'
println strDouble.isDouble()
strDouble.toDouble()
1.1.3 逻辑控制
- 顺序逻辑:单步往下执行
- 条件逻辑if else ,switch case
- 循环逻辑 while循环,for循环
//groovy 中的switch case 可以是任何类型
def x = 1.23
def result
//switch (x){
switch (x.class){
case 'foo':
result = 'found foo'
break
case 'bar':
result = 'bar'
break
case [4,5,6,'inlist']://列表
result = 'list'
break
case 12..30://范围
result = 'range'
break
case Integer:
result = 'integer'
break
case BigDecimal:
result = 'big decimal'
break
default:result = 'default'
}
println result//big decimal
//对范围的for循环
def sum = 0
for (i in 0..9){
sum += i;
}
println sum
//对list 的循环
for (i in [1,2,3,4,5,6,7,8,9]){
sum += i
}
//对map的循环
for (i in ['lili':1,'luck':2,'xiaoming':2]){
sum += i.value
}
2 闭包
2.1闭包与基本类型的使用
//闭包参数
def clouser = { String name ,int age->
println "Hello ${name},age is ${age}"
}
//clouser.call()//hello null
clouser("groovy",29)//Hello groovy,age is 29
//每一个闭包都有一个默认参数it
def clouser2 = {
println "2 Hello ${it}"
}
clouser2('Groovy')//2 Hello Groovy
//方法返回值
def clouser3 = { String name ->
return "3 Hello ${name}"
}
println clouser3('groovy')//3 Hello groovy
//也是有返回值的 返回null
def clouser4 = { String name ->
println "4 Hello ${name}"
}
println clouser4('groovy')//null
2.2 闭包的一些基础算法
int x = fab(5);
println x
//求指定number的阶乘
int fab(int number){
int result = 1
1.upto(number,{num -> result *= num})
return result
}
int fab2(int number){
int result = 1
// number.downto(1,{num -> result *= num})
//闭包放在括号内和括号外的效果是一致的
number.downto(1){
num -> result *= num
}
result result;
}
int y = cal(101)
println y
//求和 1到100
int cal(int number){
int result = 0;
number.times{
num ->result += num
}
return result
}
2.3 闭包与字符串
String str = 'the 2 and 3 is 5'
//1 each 遍历
str.each {
//每个字符串增加一倍
String temp -> print temp.multiply(2)//tthhee 22 aanndd tthhee 33 iiss 55
}
println ''
//2 find 查找符合条件的第一个
def findstr = str.find{
String s -> s.isNumber()
}
println findstr//2
//3 findAll 查找符合条件的集合
def list = str.findAll{
String s -> s.isNumber()
}
println list.toListString()//[2, 3, 5]
//4 判断字符串中是否包含数字
def result = str.any{
String s -> s.isNumber()
}
println result//true
//5 判断是否string中每一位都是数字
println str.every {String s -> s.isNumber()}//false
//6 输出字符串转大写的字符串集合
def upList = str.collect{
it.toUpperCase()
}
println upList//[T, H, E, , 2, , A, N, D, , T, H, E, , 3, , I, S, , 5]
2.4 闭包进阶
/**
* 闭包的三个重要变量: this,owner,delegate
*/
def scriptClosure= {
//this 代表闭包定义处的类
println "scriptClosure this:"+this//scriptClosure this:closureadvance.clousure1@d5b810e
//代表闭包定义处的类或者对象
println "scriptClosure owner:"+owner//scriptClosure owner:closureadvance.clousure1@d5b810e
//代表任意对象,默认值与owner一直
println "scriptClosure delegate:"+delegate//scriptClosure delegate:closureadvance.clousure1@d5b810e
}
scriptClosure.call()
println '-------------------'
//定义了一个内部类
class Person{
def static classClosure = {
println "classClosure this:"+this//
println "classClosure owner:"+owner
println "classClosure delegate:"+delegate//
}
def static say(){
def classClosure = {
println "method classClosure this:"+this
println "method classClosure owner:"+owner
println "method classClosure delegate:"+delegate//
}
classClosure.call()
}
}
Person.classClosure.call()//classClosure this/owner/delegate:class closureadvance.Person
Person.say()//method classClosure this/owner/delegat:class closureadvance.Person
//去掉static
//Person p = new Person();
//p.classClosure.call()//classClosure this:closureadvance.Person@4dbb42b7,指向了具体实例对象
//p.say()//method classClosure this:closureadvance.Person@4dbb42b7,指向了具体实例对象
println '-------------------'
//闭包中定义一个闭包
def nestClosure = {
def innerClosure = {
//这里的this表示clousure1的实例对象
println "innerClosure this:"+this//classClosure this:closureadvance.clousure1@7c711375
//在类中或者方法中定义闭包 ,this,owner.delegate是一致的,但是在闭包中定义闭包,那么三者值将不再一致,owner和delegate一致
println "innerClosure owner:"+owner//classClosure owner:closureadvance.clousure1$_run_closure2@48aca48b
println "innerClosure delegate:"+delegate//classClosure delegate:closureadvance.clousure1$_run_closure2@48aca48b
}
Person p = new Person();
innerClosure.delegate = p//人为修改默认的delegate对象,输出innerClosure delegate:closureadvance.Person@272113c4,delegate和owner不再一致
innerClosure.call()
}
nestClosure.call()
闭包的委托策略
class Student{
String name
def pretty = {"My name is ${name}"}
String toString(){
pretty.call()
}
}
class Teacher{
String name
}
def stu = new Student(name:'Sarash')
def tea = new Teacher(name:'Android')
println stu.toString()//my name is Sarash
stu.pretty.delegate = tea
println stu.toString()//my name is Sarash
//指定resolveStrategy为DELEGATE_FIRST,从delegate对象优先寻找属性和方法
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println stu.toString()//My name is Android
3 数据结构
3.1 列表
数组和list的定义
//def list = new ArrayList()//java定义方式
//定义list
def list = [1,2,3,4,5]
println list.class//class java.util.ArrayList
println list.size()//5
//定义数组
def array = [1,2,3,4,5] as int []
int[] array2 = [1,2,3,4,5]
列表的增加删除
/**
* list的添加元素
*/
list.add(6)
list.leftShift(7)
println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
list << 8
println list.toListString()//[1, 2, 3, 4, 5, 6, 7, 8]
def plusList = list+9
println plusList.toListString()//[1, 2, 3, 4, 5, 6, 7, 8, 9]
println '------------------------'
/**
* list的删除元素
*/
//list.remove(7)//移除第八个元素后的元素
//println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
//list.remove((Object)7)//移除元素7
//println list.toListString()//[1, 2, 3, 4, 5, 6]
list.removeAt(7)//移除第八个元素后的元素
println list.toListString()//[1, 2, 3, 4, 5, 6, 7]
list.removeElement(6)//移除元素6
println list.toListString()//[1, 2, 3, 4, 5, 7]
list.removeAll{return it%2 == 0}
println list.toListString()//[1, 3, 5, 7]
println list - [6,7]//[1, 3, 5]
println list.toListString()//[1, 3, 5, 7]
列表的排序
/**
* 列表的排序
*/
def sortList = [6,-3,9,2,-7,1,5]
//两种java排序方法
//从小到大排序
Collections.sort(sortList)
println sortList//[-7, -3, 1, 2, 5, 6, 9]
//添加绝对值大小规则
Comparator mc = {a,b ->
a == b?0:
Math.abs(a)<Math.abs(b)?-1:1
}
Collections.sort(sortList,mc)
println sortList//[1, 2, -3, 5, 6, -7, 9]
//groovy排序
//列表排序
sortList.sort()
sortList.sort { a, b ->
a == b ? 0
: Math.abs(a)<Math.abs(b)?1:-1
}
println sortList//绝对值从大到小[9, -7, 6, 5, -3, 2, 1]
//字符串数组排序
def sortStringList = ['abc','z','hello','groovy','java']
sortStringList.sort{it -> return it.size() }
println sortStringList//根据字符串长度排序 [z, abc, java, hello, groovy]
//列表的查找
def findList = [6,-3,9,2,-7,1,5]
int result = findList.find {return it%2 == 0}
println result//第一个偶数 6
def results = findList.findAll() {return it%2 == 0}
println results.toListString()//所有偶数 [6, 2]
def any =findList.any{return it%2 !=0}
println any//是否存在奇数 true
def every = findList.every {return it%2 == 0}
println every//是否都是偶数 false
println findList.min()//最小值-7
println findList.max()//最大值9
println findList.min{return Math.abs(it)}//绝对值最小值1
println findList.max{return Math.abs(it)}//绝对值最大值9
列表的统计
//类似sql的统计
println findList.count{return it%2 !=0}//统计奇数个数
3.2 映射
//map定义
def colors = [red:'ff0000',
gray:'00ff00',
blue:'0000ff']
//索引方式
println colors['red']
println colors.red
//添加元素
colors.yellow = 'ffff00'
println colors.toMapString()//[red:ff0000, gray:00ff00, blue:0000ff, yellow:ffff00]
colors.leftShift(organe:'ff850d')
println colors
colors.complex = [a:1,b:2]//添加一个map进去,添加任意类型
println colors//[red:ff0000, gray:00ff00, blue:0000ff, yellow:ffff00, organe:ff850d, complex:[a:1, b:2]]
println colors.getClass()//class java.util.LinkedHashMap
//删除方法
colors.remove('red')
println colors
//修改方法
colors.gray = 'huise'
println colors//[gray:huise, blue:0000ff, yellow:ffff00, organe:ff850d, complex:[a:1, b:2]]
groovy中map的操作
- 遍历
def students = [
1:[number:'01',name:'Bob',score:55,sex:'male'],
2:[number:'02',name:'Johnny',score:62,sex:'female'],
3:[number:'03',name:'Claire',score:73,sex:'female'],
4:[number:'03',name:'Amy',score:66,sex:'male']
]
//遍历
students.each {def student ->
println "the key is ${student.key},"+
"the value is ${student.value}"
}
//带索引的遍历
students.eachWithIndex{ def student, int index ->
println "index is ${index} "+
"the key is ${student.key},"+
"the value is ${student.value}"
}
//直接遍历key,value值
students.each {key,value ->
println "the key is ${key},"+
"the value is ${value}"
}
println '-------------'
- 查找
//map的查找
//找到第一个及格的仔
def entry = students.find {def student ->
return student.value.score >= 60}
println entry
//找到所有及格的仔
def entrys = students.findAll {def student ->
return student.value.score >= 60}
println entrys
//统计 输出及格的男生个数
def count = students.count {def student ->
return student.value.score >= 60 && student.value.sex =='male'
}
println count//1
//过滤 输出所有及格的人的名字
def names = students.findAll { def student ->
student.value.score >= 60
}.collect {//过滤出名字
return it.value.name
}
println names.toListString()//[Johnny, Claire, Amy]
//分组,将不及格和及格的人进行分组
def group = students.groupBy {
def student ->
return student.value.score >= 60 ? '及格':'不及格'
}
//[不及格:[1:[number:01, name:Bob, score:55, sex:male]],
// 及格:[2:[number:02, name:Johnny, score:62, sex:female], 3:[number:03, name:Claire, score:73, sex:female], 4:[number:03, name:Amy, score:66, sex:male]]]
println group.toMapString()
- 排序
//将学生由分数从低到高排序
def sort = students.sort{
def student1,def student2 ->
Number score1 = student1.value.score
Number score2 = student2.value.score
return score1==score2?0:score1<score2?-1:1
}
println sort.toMapString()
3.3 范围
def range = 1..10
println range[0]
println range.contains(10)
println range.from//起始值
println range.to//终止值
/**
* 遍历
*/
range.each { println it}
for (i in range){
println i
}
def getGrade(Number number){
def result
switch (number){
case 0..<60:
result = "${number}分,不及格"
break
case 60..70:
result = "${number}分,及格"
break
case 70..80:
result = "${number}分,良好"
break
case 80..100 :
result = "${number}分,优秀"
break
}
}
println getGrade(75)
4 面向对象
4.1 类和接口
class Person {
String name
Integer age
def increaseAge(Integer years){
this.name += years
}
}
①无论是.调用还是set/get调用,实际都是调用了set/get
def person = new Person(name:'Android',age:29)
//.name 调用的事getName()方法
println "the name is ${person.name}"+
"the age is ${person.age}"
person.increaseAge(2)
②接口,跟java的区别是不能用protected修饰
//接口不允许定义非public的方法
interface Action {
void eat()
void drink()
void play()
}
③trait 接口和抽象类的结合
trait DefaultAction {
abstract void eat()
void play(){
println 'i can play'
}
}
4.2 运行时
4.2.1 invokeMethod和methodMissing
如果调用了一个Person中不存在的方法,编译时不会不通过,运行时会报错,需要重写invokeMethod或methodMissing方法,这样运行时也不会报错了,如果两个方法都重写了,优先调用methodMissing,其次是invokeMethod
/**
* 一个方法找不到时,调用它代替
*/
def invokeMethod(String name,Object args){
return "the method is ${name},the params is ${args}"
}
def methodMissing(String name,Object args){
return "the method ${name} is missing"
}
//调用person中不存在的方法,编译时不会报错,运行时会异常
person.decrease()//Caught: groovy.lang.MissingMethodException
//重写了Person的invokeMethod方法之后,编译运行都不会出错
println person.decrease()//the method is decrease,the params is []
//如果重写了methodMissing方法,输出的是the method decrease is missing
4.2.2 metaClass 注入新的属性和方法
动态扩展使用场景,当我们使用第三方类库却抱怨其方法不够全的时候,使用groovy为第三方类库添加方法无需像java那样使用继承
//为类动态的添加一个sex属性
Person.metaClass.sex = 'male'
def person2 = new Person(name:'Android',age:29)
println person2.sex//male
person2.sex = 'female'
println "the new sex is"+person2.sex//the new sex isfemale
//为类动态的添加方法
Person.metaClass.sexUpperCase = {_-> sex.toUpperCase()}
println person2.sexUpperCase()//FEMALE
//为类动态的添加静态方法
Person.metaClass.static.createPerson={
String name,int age ->new Person(name:name,age:age)
}
def person3 = Person.createPerson('groovy',6)
println person3.name + " and " +person3.age//groovy and 6
4.2.3 ExpandoMetaClass.enableGlobally()全局注入
如果在一个类中为另外一个类拓展了一个新的方法,那么这个方法将不可以被全局使用,添加ExpandoMetaClass.enableGlobally()语句可以实现这个拓展方法的全局使用
可以简单编写一个程序模拟一下
// 模拟Person管理器
class PersonManager {
static Person createPerson(String name,int age){
return Person.createPerson(name,age)
}
}
//模拟应用程序管理器
class AppliactionManager {
static void init(){
//一次注入拓展方法,全局都可以使用
ExpandoMetaClass.enableGlobally()
//为第三方类添加方法
Person.metaClass.static.createPerson = {
String name,int age ->
new Person(name:name,age:age)
}
}
}
//模拟程序入口
class Entry {
static void main(String[] args) {
println '一个应用程序正在启动...'
//初始化
AppliactionManager.init()
println '应用程序初始化完成'
def person = PersonManager.createPerson( 'groovy',6)
println "new person name is ${person.name},age is ${person.age}"
//输出 new person name is groovy,age is 6
}
}