Call a static method on a Class object?

J

Jimi Hullegård

Lets say I have a class MyClass, that is final, and has a private
constructor. So I can't instantiate it.
Now, if I want to call a static method myMethod("hello"), I simply do
MyClass.myMethod("hello"). This is all basic stuff.
But what if I want to pass MyClass to another method, and from there call
myMethod("hello")?

This is what I thought would be possible, but it isn't:

....
doTest(MyClass.getClass(), "hello");
....

public void doTest(Class<MyClass> mc, String message)
{
mc.myMethod(message);
}

This results in:
java.lang.ClassCastException: java.lang.Class

Why doesn't this work? Is there a way to represent MyClass as a real class
(not a Class<MyClass> object), so I can call mc.myMethod(message) on it?

Is there no way to call a static method on a class object without using
reflection? If the class could be instantiated it would be easy to call the
method on that object, but even then it seems stupid to instantiate an
object just to call on a static method.

Regards
/Jimi
 
O

Oliver Wong

Jimi Hullegård said:
Lets say I have a class MyClass, that is final, and has a private
constructor. So I can't instantiate it.
Now, if I want to call a static method myMethod("hello"), I simply do
MyClass.myMethod("hello"). This is all basic stuff.
But what if I want to pass MyClass to another method, and from there call
myMethod("hello")?

This is what I thought would be possible, but it isn't:

...
doTest(MyClass.getClass(), "hello");
...

public void doTest(Class<MyClass> mc, String message)
{
mc.myMethod(message);
}

This results in:
java.lang.ClassCastException: java.lang.Class

Why doesn't this work? Is there a way to represent MyClass as a real class
(not a Class<MyClass> object), so I can call mc.myMethod(message) on it?

Is there no way to call a static method on a class object without using
reflection? If the class could be instantiated it would be easy to call
the
method on that object, but even then it seems stupid to instantiate an
object just to call on a static method.

Have you looked at the Command pattern? It sounds like you're
essentially trying to pass around methods as if they were objects, which is
what the Command pattern allows you to emulate in Java.

http://en.wikipedia.org/wiki/Command_pattern

- Oliver
 
J

Jimi Hullegård

Oliver Wong said:
Have you looked at the Command pattern? It sounds like you're
essentially trying to pass around methods as if they were objects, which
is what the Command pattern allows you to emulate in Java.

http://en.wikipedia.org/wiki/Command_pattern

Well, that is more or less what I already have done, or atleast tried to do.
The example above is greatly simplified, because I can't express the _real_
issue in a easy way, and I though there was an easy solution that would work
on the real issue aswell.
But I will try to describe the real issue (but still simpified):

I have a webserver (apache & tomcat) that has different action managers (for
login, sendMessage etc.), that all get loaded dynamically (the servlet reads
a config file, and loads the class files using a custom class loader) so I
easily can change some functionallity or add a new function withouth
reloading the webapplication. Now, I don't want to instantiate these action
managers, but instead call their static methods.

For instance, when I load the action managers, I want to set a connection
pool (a static class variable in the action manager). This is how I do it
now:

....
String storageClass = st.nextToken().trim();
Class<ActionManager> sam = loader.forceLoadClass(storageClass);
java.lang.reflect.Method setConnectionPool =
sam.getMethod("setConnectionPool", community.storage.ConnectionPool.class);
setConnectionPool.invoke(null, communityManager.getConnectionPool());


But I really would like to do something like this:

....
String storageClass = st.nextToken().trim();
(*??*) sam = loader.forceLoadClass(storageClass);
sam.setConnectionPool(communityManager.getConnectionPool());

I just though that there was something I could replace (*??*) with to get it
to work. Apperently, Class<ActionManager> doesn't work, even though the
class ActionManager has a static method setConnectionPool that takes a
ConnectionPool object).

/Jimi
 
R

Roedy Green

Have you looked at the Command pattern? It sounds like you're
essentially trying to pass around methods as if they were objects, which is
what the Command pattern allows you to emulate in Java.

The Java equivalent to method C's method parameters is the delegate.
See http://mindprod.com/jgloss/delegate. html

A delegate reference can be an interface with just one method in it, a
complex interface, an abstract class, an actual class ...
 
J

John C. Bollinger

Jimi said:
I have a webserver (apache & tomcat) that has different action managers (for
login, sendMessage etc.), that all get loaded dynamically (the servlet reads
a config file, and loads the class files using a custom class loader) so I
easily can change some functionallity or add a new function withouth
reloading the webapplication. Now, I don't want to instantiate these action
managers, but instead call their static methods.

And there is your underlying problem.

Why don't you want to instantiate the managers? Why are static methods
an advantageous implementation approach?

You should not define or use static methods without a compelling reason
to do so. On the most superficial level, this is because it will cause
you problems such as (but not limited to) the one you are having. More
fundamentally, it is because static members break *object* orientation.
For instance, when I load the action managers, I want to set a connection
pool (a static class variable in the action manager). This is how I do it
now:

...
String storageClass = st.nextToken().trim();
Class<ActionManager> sam = loader.forceLoadClass(storageClass);
java.lang.reflect.Method setConnectionPool =
sam.getMethod("setConnectionPool", community.storage.ConnectionPool.class);
setConnectionPool.invoke(null, communityManager.getConnectionPool());


But I really would like to do something like this:

...
String storageClass = st.nextToken().trim();
(*??*) sam = loader.forceLoadClass(storageClass);
sam.setConnectionPool(communityManager.getConnectionPool());

What you /should/ want to do is this:

public interface StorageActionManager {
// ...
}

// ...

String storageClass = st.nextToken().trim();
StorageActionManager sam =
loader.forceLoadClass(storageClass).newInstance();
sam.setConnectionPool(communityManager.getConnectionPool());

Since you are loading the class in question dynamically anyway, you gain
absolutely nothing (other than headaches) by trying to use static
methods instead of instance methods. My example exhibits a more typical
plug-in paradigm.
I just though that there was something I could replace (*??*) with to get it
to work. Apperently, Class<ActionManager> doesn't work, even though the
class ActionManager has a static method setConnectionPool that takes a
ConnectionPool object).

The static members of a class are not instance members of the
Corresponding Class object (which is how you are trying to use them).
Make the methods instance methods in the first place and invoke them on
an instance instead.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top