我们知道,在Java语言中,我们能够获取到Java语言的动态性,主要是通过它的反射机制来实现的。而在Groovy语言中,我们将会有很多方式来获取它的动态性,比如MOP等等。因此,在Groovy语言中,我们需要在运行期内调用某个方法,将不会使用反射机制,虽然我们仍然能够在Groovy语言中使用反射机制来达到目的;而是使用MOP机制,或者使用"duck type"。因为这些机制都比反射来得方便和灵活。
这是否说明,我们在Groovy语言的程序开发过程中将不再使用到反射机制呢?我们说,反射机制除了能够让我们在运行期内动态的调用方法以外,还有一个很重要的功能是自省功能,就是让我们能够在运行期内知道一个对象它本身的一个信息,如属于哪个Class,有哪些属性和方法,它的Class是继承了哪个父类,还是实现了哪些接口,等等。当然,还有一个很重要的功能是,能够在运行期内实例化一个类,这也是我们经常要用到的。
因此,在我们的Groovy语言编码过程中,反射机制仍然将扮演很重要的角色,MOP机制只是将反射机制的一些很弱的功能进行了扩展。
首先,我们有一个简单的类:
package reflect;
class Testor3 {
public a
def b
private String c
}
我们已经获得了一个对象,如下所示:
def t = new Testor3()
现在,我们想知道该对象"t"的类名,在Java语言中,我们必须这样获取:
println t.getClass().getName()
在Groovy语言中,由于我们广泛的使用了Gpath,上面的语句当然可以简化成下面的样子:
println t.class.name
上面的两条语句都将打印如下的结果:
reflect.Testor3
如果我们只想获取该对象的Class名,而不想带着包名,那么将是如下的样子:
println t.class.simpleName
打印的结果为:
Testor3
值得注意的是,虽然使用Gpath来获取Class相当简单,但也不是任何时候都可以这样获取的。比如:
def map = [:]
println map.class
它的打印结果将是:
null
如果你有下面的语句:
println map.class.simpleName
那么,运行它,你将得到一个空指针的违例。
在这个时候,"getClass"方法仍将派上用场:
println map.getClass()
println map.getClass().simpleName
println map.getClass().name
上面的语句都能够正确运行,得到的结果为:
class java.util.LinkedHashMap
LinkedHashMap
java.util.LinkedHashMap
得到了对象的Class以后,我们接着想得到的是它的属性。获取对象的属性有两个方法:一是获取"fields";二是获取"declaredFields"。前一个方法能够获取到该对象的公有属性;后一个方法获取的对象的所有属性。如:
def t = new Testor3()
def cls = t.class
println cls.fields
println cls.declaredFields
运行结果为:
{public java.lang.Object reflect.Testor3.a, public static java.lang.Long reflect.Testor3.__timeStamp}
{public java.lang.Object reflect.Testor3.a, private java.lang.Object reflect.Testor3.b, private java.lang.String reflect.Testor3.c, transient groovy.lang.MetaClass reflect.Testor3.metaClass, public static java.lang.Long reflect.Testor3.__timeStamp, static java.lang.Class reflect.Testor3.class$groovy$lang$MetaClass, static java.lang.Class reflect.Testor3.class$org$codehaus$groovy$runtime$ScriptBytecodeAdapter, static java.lang.Class reflect.Testor3.class$0}