//强定义类型int x = 10println x.classdouble y = 3.14println y.class//弱类型定义def a = 10println a.classdef b = 3.14println b.classdef name = "tom"println name.class输出如下 :class java.lang.Integerclass java.lang.Doubleclass java.lang.Integerclass java.math.BigDecimalclass java.lang.String
把稳:在Groovy中,所有定义的基本类型都会被系统自动装箱为相应的包装类型
3 Groovy中的String干系1. 字符串的定义
第一种办法:利用单引号

//利用单引号定义的字符串,里面的内容是不可以改变的//等价于 Java中的 String name = "hello world";def name = 'hello world'println name println name.class//输出hello worldclass java.lang.String
第二种办法:三个单引号
//之间的内容包含格式,里面的内容是什么格式的,显示出来的便是什么格式的def content = '''\line oneline twoline threeprintln content'''println content.class//输出line oneline twoline threeclass java.lang.String
第三种办法:利用双引号
//上面两种办法定义的字符串是不可改变的,但是这种办法定义的字符是可以扩展的,里面可以包含其它的变量def name = "android"def str = "hello $name"println strprintln str.class//输出hello androidclass org.codehaus.groovy.runtime.GStringImpl
把稳:第三种办法定义的字符串,里面带有 $ 符号拼接的字符类型便是GString类型,其它的都还是String类型,由此可知,Groovy已经扩展了我们的字符串,可源码可知org.codehaus.groovy.runtime.GStringImpl便是继续自GString,如下:
public class GStringImpl extends GString { private String[] strings; ....
4 GString的用法4.1 GString特性
特性1 可以拼任意表达式
def num = "3 + 5 = ${3 + 5}" //后面可以追随意任性表达式println num //输出3 + 5 = 8
问:Groovy中扩展出了GString,也便是可扩展的字符串,那么Groovy中两种字符串类型,即:String,GString,利用过程中须要把稳什么呢?如果一个方法中的参数是String,那么可不可以传GString 的呢?答:没有一点关系,利用是对开拓者透明的,完备不用管,可以相互利用。看下面一个函数,参数须要String,但是传的是GString,看看输出结果都是正常的,编译器也没有报错,以是这两种字符串是不用关心类型的,是可以随便用的
特性2 两种字符串类型可以互用
def num = "3 + 5 = ${3 + 5}" //后面可以追随意任性表达式//传的是GString类型的def result = show(num)println result//方法吸收的是String类型的String show(String message){ return message}//输出3 + 5 = 8//由此可以知道,GString,String在开拓过程中不用刻意关心类型
4.1 String常用方法普通的方法带闭包的方法 (后面讲闭包的时候讲)普通的方法center()padLeft,padRight可以直接比较,如下
def str = 'groovy'def str2 = "hello"def str3 = 'hello'println str > str2println str == str2println str2 == str3//输出falsefalsetrue//也可以直策应用索引,如println str[0]//输出g//可以传入一个范围,如println str[0..1]//输出gr//减法,把str1中包含的str2减掉,如def str1 = 'hello,world'def str2 = 'hello'println str1 - str2println str1.minus(str2)//输出,world,world//字符串反转def str3 = 'hello'println str3.reverse()//输出olleh//所有单词首字母大写def str4 = 'hello world'println str4.capitalize()//输出Hello world//判断是否是数字类型的字符串,如def str5 = '234'println str5.isNumber()//输出true//转化成数字,如def str6 = '123'println str6//输出123
逻辑掌握语句有三种
顺序掌握:单步往下实行条件逻辑:if/else 和 switch/case循环逻辑:while 和 for这些逻辑掌握是和Java中的一样的,但是又扩展了一些功能个中if/else和while和Java中的用法是一样的,switch/case和for增加了一些扩展,我们利用下面的代码来演示这两种扩展的用法,代码如下:
//switch语句def x = 3.14def resultswitch (x){ case 'test': result = 'test' //字符串 break case [4,5,6,'test']: //列表 result = 'list' break case 3..11: result = 'range' //范围 break case Integer: result = 'Integer' //类型 break case BigDecimal: result = 'BigDecimal' break default: result = 'default' break}println result//输出BigDecimal
Groovy中的switch中可以是任何类型,数据
//1 对范围的for循环def sum = 0for (i in 0..3){ sum += i}println sum//输出6//2 对List的循环def sum = 0for (i in [1,2,3,4,5,6,7,8,9]){ sum += i}println sum//输出45//3 对Map的循环def sum = 0for (i in ['tom':1,'jim':2,'xiaoming':3]){ sum += i.value println i.key}println sum//输出tomjimxiaoming6
6 Groovy中的闭包
Groovy中的闭包很强大,下面紧张从三个方向讲解闭包
1 闭包的根本详解2 闭包的利用详解3 闭包的进阶详解6.1 闭包的根本6.1.1 闭包的观点:闭包便是一段代码块,可以命名可以被调用,利用和方法类似
//1 定义一个闭包,闭包的定义便是这么大略// 便是一段代码块,可以命名,可以被调用def closer = { println "hello groovy"}//2 闭包的两种调用办法// 建议利用第一种办法调用,这样不会和方法的调用稠浊closer.call()closer()//输出hello groovyhello groovy
6.1.2 闭包的参数:普通参数和隐式参数闭包是可以传参数的,有点像Java中的lambda表达式,如下代码
//1 定义一个无参的闭包// -> 也可以省略, -> 前面的是参数,-> 后面的是闭包体def closer = { -> println "hello groovy"}//利用closer.call()closer()
//2 定义一个有参的闭包, 参数是namedef closer = { String name -> println "hello $name"}closer.call() //参数可以不传,不传便是nullcloser.call('world')closer('android')
闭包还有一个隐式的参数 it ,类似类中的this,如果定义闭包没有明确指定参数,但是调用了闭包传了参数,那么就可以在代码中利用 it 关键字,如下
//3 定义一个无参的闭包, 利用隐式的参数关键字 itdef closer = { println "hello $it"}closer.call() //参数可以不传,不传便是nullcloser.call('world')closer('android')
6.1.3 闭包的返回值:总是有返回值的闭包总是有返回值的,如果没有明确的return,返回值就决定在末了一句代码,如下
//4 闭包的返回值,如果没有return,末了一句话便是返回值def closer = { "hello world"}//返回值是"hello world"def result = closer.call()println result//输出hello world
6.2 闭包的利用闭包的利用紧张从以下几个方面讲1 与基本类型的结合利用2 与String结合利用3 与数据构造结合利用4 与文件等结合利用
6.1.1 与基本类型的结合利用
//用来求指定number的阶乘//求5的阶乘 12345 = 120int res = fab(5)println resint fab(int number){ int result = 1 1.upto(number,{ num -> result = num }) return result}
这段代码是不是很简洁,紧张的该当都在upto()方法中,我们来看一下upto()方法的源码,如下
public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) { int self1 = self.intValue();//初始值,便是1 int to1 = to.intValue();//结束值,便是5 if (self1 <= to1) {//如果初始值小于结束值,就循环 //开始从 self1到to1的循环,把每一个值都交给末了一个闭包来处理 //而在我们的闭包中,又把每一项乘的结果保存在了result变量中 for (int i = self1; i <= to1; i++) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to upto() cannot be less than the value (" + self + ") it's called on."); }
把稳,Groovy方法中,如果末了一个参数是闭包,那么圆括号是可以省略的,我们用downto()方法来演示省略圆括号的用法
既然有upto()方法,那么肯定也有downto()方法了,我们来看一下downto()方法的利用,
末了一个参数是闭包的话,方法的圆括号可以省略
//求5的阶乘 12345 = 120int res = fab2(5)println res//把稳,末了一个参数是闭包的话,方法的圆括号可以省略int fab2(int number){ int result = 1 number.downto(1){ num -> result = num } return result}
同样,downto()的源码如下:
//与upto()源码类似 public static void downto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) { int self1 = self.intValue();//初始值是5 int to1 = to.intValue();//结束值是1 if (self1 >= to1) { for (int i = self1; i >= to1; i--) { closure.call(i); } } else throw new GroovyRuntimeException("The argument (" + to + ") to downto() cannot be greater than the value (" + self + ") it's called on."); }
再看一个例子,方法只有一个闭包参数的,如下,求和
//求10以内的和int res = fab3(10)println resint fab3(int number){ int result = 0 //圆括号省略,直接跟一个闭包 number.times { num -> result += num } return result}//输出45
同样,times()方法的源码如下:
public static void times(Number self, @ClosureParams(value=SimpleType.class,options="int") Closure closure) { for (int i = 0, size = self.intValue(); i < size; i++) { closure.call(i); if (closure.getDirective() == Closure.DONE) { break; } } }
从上面几个例子可以知道,我们在写闭包的时候,有时候并不知道须要传入什么样的参数,这个时候就只能去查看源码或者官方文档了,以是查看源码和官方文档是一个比较好的习气
6.1.2 与String的结合利用
//each()方法的利用String str = 'hello world'//把每一个字符都传给闭包str.each { temp -> print temp}//输出hello world
//find()方法的利用String str = 'tom has 63 books and 3 apples'//查找第一个是数字的字符,闭包必须返回一个boolean值def result = str.find { word -> word.isNumber()}println result//输出6
可以看下find()函数是如何事情的,find()的源码如下 :
public static Object find(Object self, Closure closure) { //把闭包包装成了一个BooleanClosureWrapper工具 BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure); //遍历字符串,并把遍历的每一个字符串都交给闭包处理 for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) { Object value = iter.next(); //如果闭包返回true,解释符合条件,就把value返回 if (bcw.call(value)) { return value; } } return null; }
同理还有findAll()方法,用法如下
String str = 'tom has 63 books and 3 apples'//查找所有是数字的字符def result = str.findAll { word -> word.isNumber()}println result//输出[6, 3, 3]
//any()方法的利用String str = 'tom has 63 books and 3 apples'//判断字符串中是否包含数字def result = str.any { temp -> temp.isNumber()}println result//输出true
any()方法的事情事理如下:
public static boolean any(Object self, Closure closure) { BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure); for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) { //只要闭包条件知足,就返回true,很大略吧 if (bcw.call(iter.next())) return true; } return false; }
//every()的用法 String str = 'tom has 63 books and 3 apples'//判断字符串中是否全是数字def result = str.every { temp -> temp.isNumber()}println result//输出false
every()方法的事理如下:
public static boolean every(Object self, Closure closure) { BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure); for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) { //只要有一项不知足,立马返回 if (!bcw.call(iter.next())) { return false; } } return true; }
any()方法是只要有一项知足就返回, every()方法是只要有一项不知足就返回,恰好相反
//collect()的利用String str = 'hello world'//将字符串转化成大写def result = str.collect { temp -> temp.toUpperCase()}println result//输出[H, E, L, L, O, , W, O, R, L, D]
collect()方法的事情事理如下:
public static <T> List<T> collect(Object self, Closure<T> transform) {//把稳第二个参数,new了一个新的ArrayList() return (List<T>) collect(self, new ArrayList<T>(), transform); }
public static <T> Collection<T> collect(Object self, Collection<T> collector, Closure<? extends T> transform) { for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext(); ) { //将闭包处理过的结果都添加到新的ArrayList中 collector.add(transform.call(iter.next())); } //返回闭包处理过的结果 return collector; }
6.1 闭包的进阶利用1 闭包的关键字变量 this, owner, delegate2 闭包的委托策略
6.1.1 闭包的三个关键字 this, owner, delegate
首先先打印出这三个变量,看看输出什么
def myScript = { println "myScript this=" + this println "myScript owner=" + owner println "myScript delegate=" + delegate}myScript.call()//输出myScript this=variable.closer@48e4374myScript owner=variable.closer@48e4374myScript delegate=variable.closer@48e4374
可以看到,这三个代表的是一个意思,那么这三个关键字到底有什么差异呢?
1 this :代表闭包定义处的类2 owner :代表闭包定义处的类或者工具3 delegate:代表任意工具,但是默认是和owner是一样的如果在闭包中再定义一个闭包呢,看看这三个关键字会打印出什么
def myScript = { println "myScript this=" + this println "myScript owner=" + owner println "myScript delegate=" + delegate def innerCloser = { println "innerClouser this =" + this println "innerClouser owner=" + owner println "innerClouser delegate=" + delegate } innerCloser.call()}myScript.call()//输出myScript this=variable.closer@3d680b5amyScript owner=variable.closer@3d680b5amyScript delegate=variable.closer@3d680b5ainnerClouser this =variable.closer@3d680b5ainnerClouser owner=variable.closer$_run_closure1@3e92efc3innerClouser delegate=variable.closer$_run_closure1@3e92efc3
以是,总结下来,只有三句话:
1 this,owner,delegate这三个关键字在类和方法中定义时,指向是一样的2 在闭包中定义的闭包的时候,owner和delegate指向的是表面的闭包工具3 在修正了delegate的时候指向的时候,delegate又和其它两个不一样了如下代码,修正了delegate的指向
//定义了一个内部类class Person{}Person p = new Person()def myScript = { println "myScript this=" + this println "myScript owner=" + owner println "myScript delegate=" + delegate def innerCloser = { println "innerClouser this =" + this println "innerClouser owner=" + owner println "innerClouser delegate=" + delegate } innerCloser.delegate = p innerCloser.call()}myScript.call()//输出myScript this=variable.closer@5a63f509myScript owner=variable.closer@5a63f509myScript delegate=variable.closer@5a63f509innerClouser this =variable.closer@5a63f509innerClouser owner=variable.closer$_run_closure1@13e39c73innerClouser delegate=variable.Person@64cd705f
可以看到delegate指向了Person,不再和owner一样了
6.1.2 this, owner, delegate的浸染,也便是委托策略
用一段代码来演示变动委托策略,代码如下:
class Student{ String name //定义一个闭包 def showMe = { return "my name is $name" } @Override String toString() { return showMe(); }}class Teacher { String name}def stu = new Student(name : 'tom')def tea = new Teacher(name : 'Mrs Li')//1 没有改变委托策略的情形下println stu.toString()//2 改变闭包的委托策略stu.showMe.delegate = teastu.showMe.resolveStrategy = Closure.DELEGATE_FIRST //把委托策略改成先从delegate中找nameprintln stu.toString()//输出my name is tommy name is Mrs Li
可以看到,在不改变委托策略的情形下,输出的是my name is tom
在改变了委托策略下,把闭包的指向改成了 tea,并且把委托策略也改成了Closure.DELEGATE_FIRST ,那么查找name的时候,首先就从deleage指向处查找以是打印的是my name is Mrs Li
7 Groovy的数据构造Groovy中紧张有3种常用的数据构造。列表,映射,范围这三个数据构造比较大略,紧张以代码的形式来讲,如下
7.1 列表//1 定义列表//1.1 Java的定义办法def list = new ArrayList()//1.2 groovy中定义def list2 = [] //定义一个空的列表def list3 = [1,2,3,4] //定义一个非空的列表println list2.classprintln list3.class//输出class java.util.ArrayListclass java.util.ArrayList
可以看到,直接这样定义的便是一个ArrayList
//1.2 定义数组//在groovy中利用as关键字定义数组,把稳和列表的差异def array = [1,2,3,4] as int[]//或者利用强类型的定义办法int[] array2 = [1,2,3]
由于在Groovy中,列表和数组的定义办法类似,利用也相似,一样平常我们只利用列表就够了
//1.3 列表的排序def list = [-7,5,-3,9,4,0]list.sort()//直接一句话就排序了(默认从小到大)println list//输出[-7, -3, 0, 4, 5, 9]
//1.4 列表的排序def list = [-7,5,-3,9,4,0]//按照绝对值从大到小排序,闭包中传入的是排序规则 list.sort { a,b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? 1 : -1}println list//输出[9, -7, 5, 4, -3, 0]
def stringList = ['a','abc','hello','groovy']//1.5 按照字符串的长度大小排序stringList.sort { it -> return it.size()}println stringList//输出[a, abc, hello, groovy]
//1.6 查找列表中的第一个偶数def list = [-7,5,-3,9,4,0,6]int result = list.find { temp -> return temp % 2 == 0}println result//输出4
//1.7 查找列表中所有小于0的数def list = [-7,5,-3,9,4,0,6]def result = list.findAll { temp -> return temp < 0}println result//输出[-7, -3]
//1.8 统计列表中偶数的个数def list = [-7,5,-3,9,4,0,6]int number = list.count { return it % 2 == 0}println number//输出3
7.2 映射
//1.1 映射的定义def persons = [tom:'北京',jim:'上海',wendy:'天津']//1.2 映射的利用println persons['tom']println persons.get('jim')println persons.wendy//1.3 添加元素persons.xiaoming = '杭州'println persons//1.4 groovy中,可以添加一个繁芜的元素,比如添加一个mappersons.complex = [a:1,b:2]println persons//输出北京上海天津[tom:北京, jim:上海, wendy:天津, xiaoming:杭州][tom:北京, jim:上海, wendy:天津, xiaoming:杭州, complex:[a:1, b:2]]
groovy中的map的常用操作
//1.5 对map的遍历def students = ['tom':89,'jim':68,'wendy':56,'bob':92]students.each { def student -> println "key is " + student.key + " value is " + student.value}//输出key is tom value is 89key is jim value is 68key is wendy value is 56key is bob value is 92
//1.6 对map的遍历,带indexdef students = ['tom':89,'jim':68,'wendy':56,'bob':92]students.eachWithIndex { def student, int index -> println "key=${student.key} value=${student.value} index=${index}"}//输出key=tom value=89 index=0key=jim value=68 index=1key=wendy value=56 index=2key=bob value=92 index=3
//1.7 直接对map的遍历def students = ['tom': 89, 'jim': 68, 'wendy': 56, 'bob': 92]students.each { key, value -> println "key=${key},value=${value}"}//输出key=tom,value=89key=jim,value=68key=wendy,value=56key=bob,value=92
//1.8 查询第一个及格的人def students = ['tom': 89, 'jim': 68, 'wendy': 56, 'bob': 92]def result = students.find { student -> return student.value > 60}println result//输出tom=89
//1.9 查询所有及格的人def students = ['tom': 89, 'jim': 68, 'wendy': 56, 'bob': 92]def result = students.findAll { student -> return student.value > 60}println result//输出[tom:89, jim:68, bob:92]
//2.0 查询及格的人数def students = ['tom': 89, 'jim': 68, 'wendy': 56, 'bob': 92]def number = students.count { student -> student.value > 60}println number//输出3
//2.1 查询所有及格的人的名字def students = ['tom': 89, 'jim': 68, 'wendy': 56, 'bob': 92]def names = students.findAll { student -> student.value > 60}.collect { return it.key}println names//输出[tom, jim, bob]
7.2 范围
范围的定义
//1.1 范围的定义def range = 1..10//1.2 范围的利用println range[0] //第一个元素的值println range.contains(7) //是否包含7println range.from //范围的起始值println range.to //范围的结束值//输出1true110
范围便是这么大略,轻量级的list
8 Groovy的面向工具1 Groovy中类的方法,变量,默认的都是public2 接口和Java中的险些一样,只有一点差异,便是只能定义public的方法,不能用protected//1.1 类的定义class Person { String name int age //方法的定义 def addYear(int age){ this.age += age } @Override String toString() { return "name=${name} age=${age}" }}
//1.2 实例化一个类的工具def person = new Person()def person1 = new Person(name:'tom',age:23)def person2 = new Person(name:'tom')println person.toString()println person1.toString()println person2.toString()//输出name=null age=0name=tom age=23name=tom age=0
//1.3 get/set方法//无论是直接用 . 还是调用get/set方法,终极都是调用的get/set方法//这是和Java不一样的地方,是编译器自动为我们天生的get/setdef person = new Person(name:'tom',age:23)println "name=${person.name} , age=${person.age}"println "name=${person.getName()}, age=${person.getAge()}"//输出name=tom , age=23name=tom, age=23
元编程便是代码在实行过程中运行的期间,Groovy中,调用类的一个方法,如下 :
1 类中是否有此方法,有则调用,如果没有2 从 MetaClass中查找是否有此方法,有则调用MetaClass中的方法,如果没有3 是否重写了methodMissing()方法,有则调用methodMissing()方法,如果没有4 是否重写了invokeMethod()方法,有则invokeMethod()方法,如果没有,throw MissingMethodException紧张是: 类 --> MetaClass --> methodMissing() --> invokeMethod()
java中如果类中没有这个方法,就直接报错了,但是Groovy中,运行时是非常强大的
下面用代码来演示:如下
//先定义一个类,还是以刚才的类定义为例class Person { String name int age def addYear(int age){ this.age += age } @Override String toString() { return "name=${name} age=${age}" }}
def person = new Person(name:'tom',age:23)//调用一个没有的方法//会报 groovy.lang.MissingMethodException 非常person.show()//输出Caught: groovy.lang.MissingMethodException: No signature of method: variable.Person.show() is applicable for argument types: () values: []
//重写invokeMethod()方法class Person { String name int age def addYear(int age){ this.age += age } @Override String toString() { return "name=${name} age=${age}" } //重写invokeMethod()方法,name是调用的方法的名字,args是调用方法传的参数,一个方法找不到的时候,调用它代替 @Override Object invokeMethod(String name, Object args) { println "the method is ${name},the param is ${args}" }}//在另一个文件中,调用下面的代码 def person = new Person(name:'tom',age:23)//调用一个没有的方法person.show()//输出the method is show,the param is []
以是,由此可知,如果类中没有方法,但是重写了invokeMethod()方法,groovy是不会报错的,会调用invokeMethod()方法,可以在这里面进行提示开拓者,没有这个方法
//重写methodMissing()方法class Person { String name int age def addYear(int age){ this.age += age } @Override String toString() { return "name=${name} age=${age}" } //重写invokeMethod()方法,name是调用的方法的名字,args是调用方法传的参数 //一个方法找不到的时候,调用它代替 @Override Object invokeMethod(String name, Object args) { println "the method is ${name},the param is ${args}" }//这个方法的优先级要高于invokeMethod(),有了这个方法,将不会再调用invokeMethod()方法 def methodMissing(String name,Object args){ println "the method ${name} is missing" }}
//在另一个文件中,调用下面的代码def person = new Person(name:'tom',age:23)//调用一个没有的方法person.show()//输出the method show is missing
8.2 Groovy中的MetaClass
MetaClass可以在运行时为类动态添加属性
//为类动态添加一个属性Person.metaClass.sex = '男'def person = new Person(name:'tom',age:23)println person.sex//输出男
//为类动态添加一个方法Person.metaClass.showAge = { -> println age}def person = new Person(name:'tom',age:23)person.showAge()//输出23
//为类动态添加一个静态方法Person.metaClass.static.createPerson = { name,age -> new Person(name:name,age:age)}def person = Person.createPerson('wendy',44)println person//输出name=wendy age=44
Groovy这种动态给类添加属性和方法的特性可以不用通过重写类而添加类的功能
到现在,Groovy就讲完了,Groovy的用法还须要较多的练习才能记得牢为学习gradle打下坚实的根本。