2011-10-13 94 views
22

動態實例化一個類的Groovy的方式this question about the Groovy way to dynamically invoke a static method的答案是非常有益的,但我在遇到以下情況的麻煩:從字符串

我定義了一個簡單的Groovy類:

class Item { 
    def id = 1 
    def data = [ "a", "b" ] 
} 

然後我定義想要動態地加載Item類的簡單工具類:

class Util { 
    static def main(args) { 
    def cls = "Item" as Class 
    def instance = cls.newInstance() 
    println instance.toString() 
    } 
} 

Util.groovy是在同一文件夾中Item.groovy

當我嘗試運行Util.groovy我得到以下錯誤:

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: 
Cannot cast object 'Item' with class 'java.lang.String' 
to class 'java.lang.Class' due to: 
java.lang.ClassNotFoundException: Item 
     at Util.main(Util.groovy:3) 

,我可以讓它工作的唯一途徑是通過使用groovyc的預編譯Item.groovy,卻忽略的是點Groovy的:)

回答

28

這個工作,用underlying GroovyClassLoader

def instance = this.class.classLoader.loadClass('Item', true, false)?.newInstance() 
+1

您應該將'this.class'更改爲'this.getClass()'。通常建議使用完整的方法來避免[屬性或地圖查找(或invokeMethod覆蓋)](http://groovy.329449.n5.nabble.com/class-vs-getClass-td368617.html)。 – OverZealous

+8

爲什麼打擾我們知道這不是一張地圖?擁抱動態! ;-) –

+0

它的工作!謝謝蒂姆! :) –

5

我不得不這樣做,發現了一個有趣的方式 - 所以我想我會回來,並提到它。

我有這個問題,因爲我想傳遞一個值通過newInstance(使用非默認的構造函數),所有的解決方案似乎是工作的一點點(我很懶,好嗎?)

無論如何,假設你想創建一個新的整數(5)...試試這個:

c = "java.lang.Integer" 
p = "5" 
def result = Eval.me("return new ${c}(${p})") 
assert(result == 5) 

的工作非常出色,雖然我敢肯定,這是關於最慢的解決方案成爲可能。具有該方法適用於許多其他情況的優點。

+3

IT SEEMS javascript plagia :) –

+0

@ Bill有趣的是在知識層面上,但這實際上並不是常規的方式,就像Abdennour TOUMI說的那樣 –

+0

我同意,剛剛提到它的完整性和簡易性 - 有時候你只是寫一個單一的, off腳本,這很容易記住和靈活。 –