2011-10-13 7 views
22

Las respuestas de this question about the Groovy way to dynamically invoke a static method era muy servicial pero estoy teniendo problemas con el siguiente caso:manera maravillosa para crear dinámicamente una instancia de una clase de cadena

que define una clase simple maravilloso:

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

que entonces se define una clase sencilla utilidad que quiere cargar dinámicamente la clase de artículo:

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

Util.groovy está en la misma carpeta que Item.groovy

Cuando trato de ejecutar Util.groovy me sale el siguiente error:

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) 

La única manera que podía hacerlo era mediante el uso de trabajo groovyc precompilar Item.groovy, pero esto pasa por el punto de ser maravilloso :)

Respuesta

28

esto funciona, utilizando el underlying GroovyClassLoader:

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

Probablemente debería cambiar 'this.class' a' this.getClass() '. En general, se recomienda utilizar el método completo para evitar [propiedades o correlaciones de mapas (o invalidaciones de invoqueMétodo)] (http://groovy.329449.n5.nabble.com/class-vs-getClass-td368617.html). – OverZealous

+8

¿Por qué molestarse cuando sabemos que esto no es un mapa? ¡Abraza la dinámica! ;-) –

+0

¡Funcionó! Gracias Tim! :) –

5

sólo tenía que hacer esto y encontré una manera interesante - así que pensé que me gustaría volver y lo menciono.

que tenía un problema con esto porque quería pasar un valor a newInstance (utilizar un constructor no predeterminado) y todas las soluciones que parecía ser un poco de trabajo (soy vago, ¿de acuerdo?)

de todos modos, supongamos que desea crear un nuevo entero (5) ... prueba esto:

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

funcionó muy bien aunque estoy seguro de que se trata de la solución más lenta posible. Tiene la ventaja de que el método es aplicable a muchas otras situaciones.

+3

PARECE javascript plagia :) –

+0

@Bill Interesante a nivel intelectual, pero esto no es realmente genial, como Abdennour TOUMI dijo –

+0

Estoy de acuerdo, lo mencioné por completo y fácil, a veces solo escribes uno. off script y esto es fácil de recordar y flexible. –

Cuestiones relacionadas