Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy way to dynamically invoke a static method

Tags:

groovy

I know in Groovy you can invoke a method on a class/object using a string. For example:

Foo."get"(1)   /* or */ String meth = "get" Foo."$meth"(1) 

Is there a way to do this with the class? I have the name of the class as a string and would like to be able to dynamically invoke that class. For example, looking to do something like:

String clazz = "Foo" "$clazz".get(1) 

I think I'm missing something really obvious, just am not able to figure it out.

like image 552
John Wagenleitner Avatar asked Feb 23 '09 09:02

John Wagenleitner


People also ask

Can a static method be invoked?

We can invoke a static method by using its class reference. An instance method is invoked by using the object reference.

Can you invoke a static method from an instance?

A static method in Java (also called class method) is a method that belongs to the class and not the instance. Therefore, you can invoke the method through the class instead of creating an instance first and calling the method on that instance.

How do I invoke static?

Invoking a public static Method Once we hold the method object, we can invoke it simply by calling the invoke method. It's worthwhile to explain the first argument of the invoke method. If the method is an instance method, the first argument is the object from which the underlying method is invoked.

How is non static method is invoke?

But when we try to call Non static function i.e, TestMethod() inside static function it gives an error - “An object refernce is required for non-static field, member or Property 'Program. TestMethod()”. So we need to create an instance of the class to call the non-static method.


2 Answers

As suggested by Guillaume Laforge on Groovy ML,

("Foo" as Class).get(i) 

would give the same result.

I've tested with this code:

def name = "java.lang.Integer" def s = ("$name" as Class).parseInt("10") println s 
like image 55
chanwit Avatar answered Sep 21 '22 12:09

chanwit


Try this:

def cl = Class.forName("org.package.Foo") cl.get(1) 

A little bit longer but should work.

If you want to create "switch"-like code for static methods, I suggest to instantiate the classes (even if they have only static methods) and save the instances in a map. You can then use

map[name].get(1) 

to select one of them.

[EDIT] "$name" is a GString and as such a valid statement. "$name".foo() means "call the method foo() of the class GString.

[EDIT2] When using a web container (like Grails), you have to specify the classloader. There are two options:

Class.forName("com.acme.MyClass", true, Thread.currentThread().contextClassLoader) 

or

Class.forName("com.acme.MyClass", true, getClass().classLoader) 

The first option will work only in a web context, the second approach also works for unit tests. It depends on the fact that you can usually use the same classloader as the class which invokes forName().

If you have problems, then use the first option and set the contextClassLoader in your unit test:

def orig = Thread.currentThread().contextClassLoader try {     Thread.currentThread().contextClassLoader = getClass().classLoader      ... test ... } finally {     Thread.currentThread().contextClassLoader = orig } 
like image 40
Aaron Digulla Avatar answered Sep 19 '22 12:09

Aaron Digulla