The answers of this question about the Groovy way to dynamically invoke a static method were very helpful but I'm having trouble with the following case:
I defined a simple Groovy class:
class Item { def id = 1 def data = [ "a", "b" ] }
I then defined a simple utility class that wants to dynamically load the Item class:
class Util { static def main(args) { def cls = "Item" as Class def instance = cls.newInstance() println instance.toString() } }
Util.groovy is in the same folder as Item.groovy
When I try to run Util.groovy I get the following 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)
The only way that I could make it work was by using groovyc to precompile Item.groovy, but this misses the point of being Groovy :)
The Class method in Groovy has a newInstance() to dynamically create a new instance of a given class. We can use an Object array or Map as argument if we want to invoke the non-default constructor of the class. This seems to be deprecated in the JRE and needs to be replaced by Blog. getDeclaredConstructor().
If your class has a no-arg constructor, you can get a Class object using Class. forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
In Groovy, we can add a method named call to a class and then invoke the method without using the name call . We would simply just type the parentheses and optional arguments on an object instance. Groovy calls this the call operator: () . This can be especially useful in for example a DSL written with Groovy.
Groovy is a fully fledged object-oriented (OO) language supporting all of the OO programming concepts that are familiar to Java developers: classes, objects, interfaces, inheritance, polymorphism, and others.
This works, using the underlying GroovyClassLoader
:
def instance = this.class.classLoader.loadClass( 'Item', true, false )?.newInstance()
I just had to do this and found an interesting way--so I thought I'd come back and mention it.
I had A problem with this because I wanted to pass a value to newInstance (use a non-default constructor) and all the solutions seemed to be a little bit of work (I'm lazy, okay?)
Anyway, suppose you want to create a new Integer(5)... try this:
c = "java.lang.Integer" p = "5" def result = Eval.me("return new ${c}(${p})") assert(result == 5)
Worked really well although I'm sure it's about the slowest solution possible. Has the advantage that the method is applicable to many other situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With