我知道在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