Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy way to dynamically instantiate a class from String

Tags:

groovy

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 :)

like image 739
Miguel Pardal Avatar asked Oct 13 '11 18:10

Miguel Pardal


People also ask

How do I instantiate a class in 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().

How do you instantiate a class dynamically in Java?

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).

How do you call a class in Groovy?

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.

Is Groovy object oriented?

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.


2 Answers

This works, using the underlying GroovyClassLoader:

def instance = this.class.classLoader.loadClass( 'Item', true, false )?.newInstance() 
like image 72
tim_yates Avatar answered Sep 23 '22 09:09

tim_yates


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.

like image 35
Bill K Avatar answered Sep 25 '22 09:09

Bill K