这是我到目前为止所做的:
static def traceMethods(Class clazz) {
def mc = clazz.metaClass
mc.static.invokeMethod = { String name, args ->
List types = args.collect { it == null ? null : it.getClass() }
MetaMethod metmeth = mc.getStaticMetaMethod(name, *types) //throws exception sometimes when it shouldnt
println "Starting method $name"
def result = metmeth.doMethodInvoke(delegate, args)
println "Finished method $name"
return result
}
}
这在大多数时候都很完美。但是,有时对getStaticMetaMethod
的调用会抛出异常。
编辑:它抛出的例外是:
groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method org.codehaus.groovy.runtime.HandleMetaClass#getStaticMetaMethod.|Cannot resolve which method to invoke for [class java.lang.String, null] due to overlapping prototypes between:|?[class java.lang.String, class [Ljava.lang.Object;]|?[class java.lang.String, class [Ljava.lang.Class;]
at groovy.lang.MetaClassImpl.chooseMostSpecificParams(MetaClassImpl.java:2906)
at groovy.lang.MetaClassImpl.chooseMethodInternal(MetaClassImpl.java:2859)
at groovy.lang.MetaClassImpl.chooseMethod(MetaClassImpl.java:2800)
at groovy.lang.MetaClassImpl.getMethodWithCachingInternal(MetaClassImpl.java:1181)
at groovy.lang.MetaClassImpl.createPogoCallSite(MetaClassImpl.java:3022)
答案 0 :(得分:0)
你的意思是做以下事情吗?
MetaMethod metmeth = mc.getStaticMetaMethod(name, types as Class[])
让我们说args是[1,"abc",true]
。这会导致types
成为[Integer,String,Boolean]
。
在此处使用扩展运算符(*
)会导致Groovy尝试使用getStaticMetaMethod(String,Integer,String,Boolean)
之类的签名调用方法。这可能不是你想要的。
但是,由于没有该签名的方法,Groovy回退到试图将*type
转换为适当的类似集合的对象。在这种情况下,它可以选择Class[]
或Object[]
,因为方法getStaticMetaMethod(String,Class[])
和getStaticMetaMethod(String,Object[])
都存在。
当args只包含空值时,Groovy无法决定是否转换为Class[]
或Object[]
,因此也是异常。使用显式强制转换(types as Class[]
)可以使您的意图清晰到Groovy并消除歧义。
顺便说一句,您可以使用原始代码重现例外:
class A {
static def doX(String s) { }
}
traceMethods(A)
A.doX(null)