我知道在Groovy中,您可以使用字符串调用类/对象上的方法。例如:
Foo."get"(1)
/* or */
String meth = "get"
Foo."$meth"(1)
有没有办法在课堂上这样做?我将类的名称作为字符串,并希望能够动态调用该类。例如,希望做类似的事情:
String clazz = "Foo"
"$clazz".get(1)
我想我错过了一些非常明显的东西,但我无法弄明白。
答案 0 :(得分:29)
根据Guillaume Laforge对Groovy ML的建议,
("Foo" as Class).get(i)
会得到相同的结果。
我已使用此代码进行了测试:
def name = "java.lang.Integer"
def s = ("$name" as Class).parseInt("10")
println s
答案 1 :(得分:16)
试试这个:
def cl = Class.forName("org.package.Foo")
cl.get(1)
稍微长一点但应该有用。
如果你想为静态方法创建类似“switch”的代码,我建议实例化类(即使它们只有静态方法)并将实例保存在地图中。然后你可以使用
map[name].get(1)
选择其中一个。
[编辑] "$name"
是一个GString
,因此是一个有效的声明。 "$name".foo()
表示“调用类foo()
的方法GString
。
[EDIT2] 使用Web容器(如Grails)时,必须指定类加载器。有两种选择:
Class.forName("com.acme.MyClass", true, Thread.currentThread().contextClassLoader)
或
Class.forName("com.acme.MyClass", true, getClass().classLoader)
第一个选项仅适用于Web上下文,第二个选项也适用于单元测试。这取决于您通常可以使用与调用forName()
的类相同的类加载器。
如果您遇到问题,请使用第一个选项并在单元测试中设置contextClassLoader
:
def orig = Thread.currentThread().contextClassLoader
try {
Thread.currentThread().contextClassLoader = getClass().classLoader
... test ...
} finally {
Thread.currentThread().contextClassLoader = orig
}
答案 2 :(得分:3)
增加Chanwit的答案,说明创建实例:
def dateClass = 'java.util.Date' as Class
def date = dateClass.newInstance()
println date
答案 3 :(得分:2)
这是另一种方式
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
def target = application.domainClasses.find{it.name == 'ClassName'}
target.clazz.invokeMethod("Method",args)
使用此功能,您无需指定包名称。如果你在两个不同的包中有相同的类名,请注意。
答案 4 :(得分:1)
Groovy ML上的Melix指出我在动态类方法调用的“正确”方向上一段时间,非常有用:
// 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非常有趣; - )
答案 5 :(得分:1)
我正在运行1.8.8版本的groovy ......简单的例子可以运行。
Import my.Foo
def myFx="myMethodToCall"
def myArg = 12
Foo."$myFx"(myArg)
按预期和期望调用Foo.myMethodToCall(12)。我不知道是否一直如此。