我知道在Groovy中,您可以使用字符串在类/对象上调用方法。例如:Groovy方法动态调用静态方法
Foo."get"(1)
/* or */
String meth = "get"
Foo."$meth"(1)
有没有办法与这个类做到这一点?我把这个类的名字看作一个字符串,并希望能够动态地调用这个类。例如,寻找类似的东西:
String clazz = "Foo"
"$clazz".get(1)
我想我错过了一些非常明显的东西,只是无法弄清楚。
我知道在Groovy中,您可以使用字符串在类/对象上调用方法。例如:Groovy方法动态调用静态方法
Foo."get"(1)
/* or */
String meth = "get"
Foo."$meth"(1)
有没有办法与这个类做到这一点?我把这个类的名字看作一个字符串,并希望能够动态地调用这个类。例如,寻找类似的东西:
String clazz = "Foo"
"$clazz".get(1)
我想我错过了一些非常明显的东西,只是无法弄清楚。
试试这个:
def cl = Class.forName("org.package.Foo")
cl.get(1)
有点长,但应该工作。
如果你想为静态方法创建类似“switch”的代码,我建议实例化这些类(即使它们只有静态方法)并将这些实例保存在一张地图中。然后您可以使用
map[name].get(1)
选择其中之一。
[编辑]"$name"
是一个GString
和这样一个有效的陈述。 "$name".foo()
意味着“调用方法的类GString
的foo()
[EDIT2]当使用Web容器(如Grails的),你必须指定的类加载器有两个选项:
Class.forName("com.acme.MyClass", true, Thread.currentThread().contextClassLoader)
或
Class.forName("com.acme.MyClass", true, getClass().classLoader)
第一个选项将仅在网络环境中工作,第二种方法也适用于单元测试。这取决于事实,你通常可以使用与调用forName()
的类相同的类加载器。
如果你有问题,那么在你的单元测试使用第一个选项,并设置contextClassLoader
:
def orig = Thread.currentThread().contextClassLoader
try {
Thread.currentThread().contextClassLoader = getClass().classLoader
... test ...
} finally {
Thread.currentThread().contextClassLoader = orig
}
我希望找出是否有一个“Groovy”做Class.forName的方式,类似于他们如何轻松地反思方法。我很欣赏你的回答,并怀疑这可能是唯一的方法。 – 2009-02-23 16:20:38
由于Groovy的ML建议由纪尧姆·拉法格,
("Foo" as Class).get(i)
将给予相同结果。
我这个代码进行测试:
def name = "java.lang.Integer"
def s = ("$name" as Class).parseInt("10")
println s
这里的另一种方式
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
def target = application.domainClasses.find{it.name == 'ClassName'}
target.clazz.invokeMethod("Method",args)
有了这个,你不需要指定包名。但要小心,如果你在两个不同的包中有相同的类名。
的增强,以实例的Chanwit的回答说明创作:
def dateClass = 'java.util.Date' as Class
def date = dateClass.newInstance()
println date
Melix Groovy的ML指出我在动态类方法invokation“正确”方向一段时间回来,非常有用:
// define in script (not object) scope
def loader = this.getClass().getClassLoader()
// place this in some MetaUtils class, invoked on app startup
String.metaClass.toClass = {
def classPath = getPath(delegate) // your method logic to determine 'path.to.class'
Class.forName(classPath, true, this.loader)
}
// then, anywhere in your app
"Foo".toClass().bar()
您可以创建另一个字符串metaClass方法来创建实例,并根据需要进行重构:
String.metaClass.toObject = {
def classPath = getPath(delegate)
Class.forName(classPath, true, this.loader).newInstance()
}
Groovy是纯粹的乐趣; - )
我正在运行版本1.8.8 groovy ...和简单的例子工程。
Import my.Foo
def myFx="myMethodToCall"
def myArg = 12
Foo."$myFx"(myArg)
按预期和期望调用Foo.myMethodToCall(12)。我不知道这是否一直如此。
类不会被“调用” - 只有方法。你想要调用什么?你想要做一些像MyOwnClass.static_property()?或myInstanceOfClass.methodName()? – Chii 2009-02-23 12:49:17
我的猜测是他想调用一个类的静态方法。 – 2009-02-23 12:52:54
我想调用一个类,一个我不知道直到运行时间的类的静态方法。我知道Java的方式是使用Class.forName,只是好奇,如果有Groovy的方式来做到这一点像他们的方法。 – 2009-02-23 16:18:18