前言:
眼前同学们对“groovy与java”大概比较关怀,看官们都想要分析一些“groovy与java”的相关知识。那么小编也在网摘上网罗了一些对于“groovy与java””的相关知识,希望各位老铁们能喜欢,看官们一起来学习一下吧!gradle脚本是基于groovy语言开发的,想要学好gradle必须先要对groovy有一个基本的认识
1. Groovy特点groovy是一种DSL语言,所谓的DSL语言,就是专门针对某一特定领域的语言,专精而不专广是一种基于JVM的开发语言,也是编译成class字节码文件结合和Python,Ruby,PHP等语言的特性,写脚本非常强大Groovy可以与Java完美结合,而且可以使用Java所有的类库语法上支持动态类型,闭包等新语言的特性支持面向过程和面向对象编程2. Groovy语法精讲1 变量的类型和定义-变量的类型分两种基本类型:和java的基本类型一样,int,long,double,float,boolean,byte,String等
注意Groovy中,这些基本类型实际上都会被系统装箱为对应的对象类型,比如int就会被自动装箱为Integer对象类型:和Java的一样变量的定义强类型定义:如 int a=10 ,指定变量的类型弱类型定义:如 def b = 5,系统根据后面的值自动判断b是什么类型Groovy语法小点语句后面可以不带分号,也可以带分号,如定义一个变量 int a = 10输出一句话,直接println就行了,圆括号也可以省略,如 println "hello,world"定义变量或者函数可以使用关键字def ,也可以按照Java的语法格式定义,如def name="tom"
如下面的代码
//强定义类型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
5 Groovy中的逻辑控制
逻辑控制语句有三种
顺序控制:单步往下执行条件逻辑: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//输出tomjimxiaoming66 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的阶乘 1*2*3*4*5 = 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的阶乘 1*2*3*4*5 = 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//输出37.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
8.1 Groovy中的元编程
元编程就是代码在执行过程中运行的时期,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 missing8.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打下坚实的基础。
标签: #groovy与java