2021SC@SDUSC
11、Groovy类和对象的源码探讨
Groovy类的特色
我们知道,Groovy的类和对象相较于java有了一些新的特色:
(1)不需public修饰符,Groovy的默认访问修饰符就是public
(2)不需要类型说明,Groovy也不关心变量和方法参数的具体类型。
(3)不需要getter/setter方法,所有类成员(如果是默认的public)根本不用通过getter/setter方法引用它们(当然,如果一定要通过getter/setter方法访问成员属性,Groovy也提供了它们)。
(4)不需要构造函数,不再需要程序员声明任何构造函数。
(5)不需要return,Groovy中,方法不需要return来返回值。
(6)不需要(),Groovy中方法调用可以省略()(构造函数除外)。
这篇博客,就让我们根据Groovy的源码探讨一下Groovy为类和对象做了哪一些的封装和功能的补充。
Groovy类源码探讨
我们先写一个最简单的Groovy类:
class Hello{
int a;
}
然后我们使用groovyc
命令把这个Groovy类转化成一个java类,然后再进行分析,我们可以得到一个简单的解开封装的类结果:
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import groovy.transform.Internal;
import java.beans.Transient;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class Hello implements GroovyObject {
private int a;
@Generated
public Hello() {
CallSite[] var1 = $getCallSiteArray();
super();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
@Generated
@Internal
@Transient
public MetaClass getMetaClass() {
MetaClass var10000 = this.metaClass;
if (var10000 != null) {
return var10000;
} else {
this.metaClass = this.$getStaticMetaClass();
return this.metaClass;
}
}
@Generated
@Internal
public void setMetaClass(MetaClass var1) {
this.metaClass = var1;
}
@Generated
public int getA() {
return this.a;
}
@Generated
public void setA(int var1) {
this.a = var1;
}
}
我们可以发现,这个类是实现了GroovyObject接口的,这个包括重写了getMetaClass,setMetaClass方法这些都是为了实现Groovy类对象元编程和为Groovy类添加封装方法代理的,这些我们在之前博客上重点分析过,这里就一笔粗略带过了。
Groovy会自动生成一个构造函数,在创建Groovy对象的时候,会自动把传入的参数创建一个Binding对象,然后这个Binding里面则自动创建一个map存储参数,不再需要程序员声明任何构造函数,因为实际上只需要两个构造函数(1个不带参数的默认构造函数,1个只带一个map参数的构造函数–由于是map类型,通过这个参数可以构造对象时任意初始化它的成员变量)。
而各个属性默认上是私有属性,而它的set、get函数都是Groovy工具自动生成的。
Groovy类的函数除了构造函数外其余的都不用加括号,则是因为Groovy类默认实现了接口GroovyObject,所有的对象属性都被GroovyObject所拦截了,由invoke再反射实现。