初识Groovy
- 1.基本语法
groovy作为动态的脚本语言,底层实现为java,groovy文件在运行时,先被解释成.class文件,本身为脚本语言,所以他的优势在于动态加载;
(1)定义变量及方法
//.groovy
def str = new String()
def str1 = 'abc'
def str2 = "$str1 : 556"
def getSome(var12) {
println var12
}
在这里groovy不重视类型,但是也可以像java一样,重视类型,基本操作与java相同;值得注意的是,在groovy中单引号和双引号是有不同功能的,只是定义一个字符串,可以直接用单引号,在双引号中可以格式化字符串,就像例子中的$str,会被解释成abc
(2)强大的闭包
//读取文件,按行输出
new File('filePath').eachline('encoding') {
//closure
line -> println line
}
//定义闭包函数
def foo = {
key, value ->
..dosomething
println "$key : $value"
}
//调用
foo.call('name', 'Mr.zou')
def list = [1,2,3,4,5]
list.each {
println it
}
闭包其实类似于java中的lambda函数,在最后一个例子中,使用一个变量为it,这个是groovy的内置变量,在这里表示循环的item,可以看到在调用调用each的时候,方法没有小括号,这是个有趣的地方,因为groovy允许如果函数的最后一个参数是一个闭包的话,那么小括号可以省略
(3)文件操作
上面的例子已经提到文件的读方法,要比java简单的多,下面看一下写的例子
//补充读文件的方法
def file = new File('filepath')
println file.text //直接输出文件文本
//写文件
def file = new File("E:/test.txt")
file.withWriter { writer ->
writer << 'xixi \r\n'
writer << 'haha \r\n'
}
file对象提供了丰富的流对象,操作文件更方便
(4)json
groovy提供可很强大的针对json的操作功能,核心的类JsonSlurper,JsonOutput
def jsonStr = "{\"state\":{\"name\":\"zouYu\",\"age\":12}}"
def parser = new JsonSlurper().setType(JsonParserType.LAX)
def jsonResp = parser.parseText(jsonStr) as HashMap
def info = jsonResp.state as HashMap
def user = new Expando(info)
user.setProperty('abc', false)
println(user)
println JsonOutput.toJson(user)
上面的结果是
{name=zouYu, age=12, abc=false}
{“name”:”zouYu”,”age”:12,”abc”:false}
其中Expando稍后再讲,先说一下JsonSlurper类,可以看到在初始化对象之后调用了setType方法,这个参数的作用是,允许json字符串存在注释或者没有引号的字段,这个是一个非常好的功能,推荐使用这种模式,还有一点就是在定义info时,后面使用了as,这意味着json字符串转换成类型时,可以定义它的类型
相当于,如果我已经确定这个json字符串对应的实体对象,那么我可以直接使用
def student = parser.parseText(jsonStr) as Student
这样就可以直接实例化一个student对象;JsonOutput提供了多种类型转换成json字符串的方法
这里生成的json字符串可以更直观的看出类的关系,但是这里需要注意的是,中文会被转换成unicode编码,在java中Unicode编码字符串toString()之后会自动转换成中文,但是这里不行
(5)面向对象
在做groovy开发时,可以查看groovy解释生成的.class文件
我在同一个文件中定义了三个class,解释之后会生成3个class文件,首先我们开一下简单类
class Student {
String name
int age
School school
}
>>生成的class文件
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling;
public class Student implements GroovyObject {
private String name;
private int age;
private School school;
public Student() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
public Student(Object name, Object age, Object school) {
CallSite[] var4 = $getCallSiteArray();
MetaClass var5 = this.$getStaticMetaClass();
this.metaClass = var5;
this.name = (String)ShortTypeHandling.castToString(name);
this.age = DefaultTypeTransformation.intUnbox(age);
this.school = (School)ScriptBytecodeAdapter.castToType(school, School.class);
}
public String getName() {
return this.name;
}
public void setName(String var1) {
this.name = var1;
}
public int getAge() {
return this.age;
}
public void setAge(int var1) {
this.age = var1;
}
public School getSchool() {
return this.school;
}
public void setSchool(School var1) {
this.school = var1;
}
}
很明显,groovy把封装做的很好,属性私有,对外暴露setter/getter方法,还有,groovy对方法也进行了处理,方法的默认返回值为方法的最后一行代码,一切的工作都是在努力的减少工作量;
在面向对象中特别值得一提的就是元对象编程,什么意思呢?假如你现在想对一个没有任何属性的类,添加属性并赋值,怎么办,直接操作肯定是报错的,groovy在这里提供了一个方法
class Student {
static void main(String[] args){
Student.metaClass.name = { -> 'Mr.zou'}
def stu = new Student()
println stu.name
}
}
对于这种模式,相当于在Student类上永久加了这个name属性,之后初始化都会带有这个属性,还有要介绍的两个类,Expando,ExpandoMetaClass,后者类似于上面的操作,主要说一下Expando,这个东西很好用,比如说我有这样一个场景,我从接口中收到一个json串,我想不通过反序列化,直接将json转换成对象并且对这个对象的属性进行增改组装,然后调用其他接口,代码如下
def parser = new JsonSlurper().setType(JsonParserType.LAX)
def jsonResp = parser.parseText(var12) as HashMap //var12为jsonString
def student = new Expando(jsonResp as HashMap)
student.setProperty(propName, propValue);
student.getproperty(propName)
这个是Expando类提供的api和构造函数
在groovy中实现一个GroovyInterceptable类也是可以进行动态赋值的,invokeMethod相当于java反射
public Object invokeMethod(String name, Object args) {
return this.getMetaClass().invokeMethod(this, name, args);
}
这是源码,GroovyObjectSupport抽象类继承自GroovyObject
正在学习,写的不好欢迎纠正,未完待续……..