Archived

This topic is now archived and is closed to further replies.

[java] How do I call a method in java when I don't know what it is beforehand?

This topic is 5822 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am wondering if something like this is even possible. In VB there is a way to call a method by using CallByName or something like that where you just pass the name of the method as a string. Is there a similiar way to do that with the name of a method for a class?

Share this post


Link to post
Share on other sites
Check out the Class and Method classes in the java.lang.reflect package.

Share this post


Link to post
Share on other sites
The java.lang.reflect package will do what you''re asking, but be aware that it''s sloooow. There are faster ways of calling methods dynamicly. Polymorphism, an indexed list of Runnable objects, etc.
As always, performance test your code, see what works best in your situation.

"If consquences dictate our course of action, it doesn''t matter what''s right, it''s only wrong if you get caught."
- Tool

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by WayfarerX
The java.lang.reflect package will do what you''re asking, but be aware that it''s sloooow. There are faster ways of calling methods dynamicly. Polymorphism, an indexed list of Runnable objects, etc.
As always, performance test your code, see what works best in your situation.

"If consquences dictate our course of action, it doesn''t matter what''s right, it''s only wrong if you get caught."
- Tool


I am trying to right a script engine and I wanted to do this instead of using a bunch of huge select case statements. I don''t think I could use polymorphism for that. I have not had a lot of experience w/ multi-threading and haven''t heard about indexing a list of runnable objects? What is that? Can you provide to a link with some info on that?

Anyway, thanks a bunch. The reflection API is working out for me.

Share this post


Link to post
Share on other sites
This post might be a little long-winded, so beware.

To use an indexed list of Runnables is easy and doesn't require any multi-thread code.
java.lang.Runnable is a simple interface that declares a single function: public void run(). Classes that implement the Runnable interface are most commonly passed to new Threads so that the Thread can call the Runnable's run() method in a new thread. However, the runnable object is also a tool you can use to simulate passing pointers to functions like in C.
EXAMPLE: Lets say you're writing a script for an AI. There are three methods the script should be able to call "MoveForward()", "MoveLeft()", & "MoveRight()". First thing you do is create 3 classes that implement Runnable, on for each method:

  

public class MForwardRunner implements Runnable {
//...

public void run () {
// Call your moving forward code

}
//...

}
public class MLeftRunner implements Runnable {
//...

public void run () {
// Call your moving left code

}
//...

}
public class MRightRunner implements Runnable {
//...

public void run () {
// Call your moving right code

}
//...

}



Next, create a Hashtable with all of your functions indexed by their name:

  

Hashtable scriptFuncTbl = new Hashtable();
scriptFuncTbl.put("MoveForward()", new MForwardRunner());
scriptFuncTbl.put("MoveRight()", new MRightRunner());
scriptFuncTbl.put("MoveLeft()", new MLeftRunner());



Then, to call a function from a script, just look up the Runnable in the hashtable and run it

  

void runScriptFunc (String funcName)
{
Runnable r = (Runnable)scriptFuncTbl.get(funcName);
if (r != null) r.run();
}



This should work fine, and it will probably be faster than the reflection API (but be sure and test, test, test), but this isn't how I'd nessicarily do it.

If I was building a scripting language to run in a Java app (which I have done before), I would think about the fact that Java itself is essintially a scripting language, it just get's compiled into byte codes beforehand. Java also has all of the features you could want in a full-featured scripting language, is heavily supported by an industry full of developers, and will probably beat the pants off any generalized language you or I could come up with and implement when it comes to speed.
So think about this. You create an abstract class called "AIScript" or whatever. In this class you implement a bunch of methods that the script should be able to call (like an IsEnemyInFrontOfMe() function or the MoveForward/Right/Left functions from earlier). Finally, you add one abstract method called "RunScript()" or something.
Then, to actually make a script, you create another class that sub-classes AIScript and implements the RunScript() function. What does this do for you?
1) Easy upkeep of the interface scripts have into your game. Simply change the AIScript class and viola! No hashtables, no reflection API.
2) You can completely skip writing the parser/lexer/etc. for your engine, saving mucho development time.
3) The compiled Java code will run faster than just about anything you could implement.

You could even have a little utility that would take code written by level designers in the format:

  

// AI Script file

while (IsAlive())
{
if (IsEnemyInFrontOfMe())
{
Attack();
}
else
{
FaceTowardsEnemy();
MoveForward();
}
}



and flow it into a template file:

  

class AISCRIPT_[ScriptFileName] extends AIScript
{
public void runScript ()
{
[ScriptContents]
}
}



replacing "[ScriptFileName]" with the name of the script file and "[ScriptContents]" with the contents of the script. Compile and you have a class file that is loadable into your game. This also makes it easier for users to mod your game since the "scripting language" you're using is completely documented in hundreds of books and thousands of online tutorials.

Just food for thought (the length of this post would imply a feast for thought). If you have any further questions about this stuff just post here or email me at wayfarerx@hotmail.com.

"If consquences dictate our course of action, it doesn't matter what's right, it's only wrong if you get caught."
- Tool

Edited by - wayfarerx on September 10, 2001 4:51:03 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you want to really write a good scripting language, read up on the java virtual machine specification . This contains information on writing your own byte code class files. Then you can overload a ClassLoader that can load your own custom scripts which are compiled to class byte code. To interogate an object''s methods, just use the getClass() method. Then use the methods of the class to get all the methods and fields. From the Method class returned by getMethod("name"), you can call invoke( Object, Object[]) with object referring to the target object, and Object[] referring to an array of arguments for the functions.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Sorry to dig up an old post...

I''m a relative java newbie, and I really like the method of scripting WayfarerX has described. One question though, is it possible to compile a ''script'' into a class file, and the load and create an instance of it during runtime? I''m working on a simple multiplayer game, and it would be nice if I could add new scripts in without having to restart the game.

Share this post


Link to post
Share on other sites
Yes, it is very possible. Dynamic compilation and class loading can get very good performance from scripting. The solution can also be used even when you do not use Java as the scripting language, such as when you use an entirely graphical tool to create the scripts. You just need some way to create JVM bytecode from whatever representation the script is created in.

Share this post


Link to post
Share on other sites
Well, if its possible to do it in java, how do I go about it? Are there classes within the java api that can be used to compile during runtime?

Share this post


Link to post
Share on other sites
No compiler classes are included in the standard Java API so you will either have to write your own or use 3rd party software. There might be publicly available packages out there that you can integrate in your product or you can possibly use the javac compiler from Sun, I think they allow you to distribute it with your apps nowdays.

Share this post


Link to post
Share on other sites
Btw, since this post is really old it might be worth mentioning that Wayfarer''s statement about reflection being slow might not necessarily be true anymore. At least Sun propaganda claims that parts of the reflection mechanism have been reimplemented in JDK1.4 and that method calls through reflection are now 20 times faster than they were in JDK1.3.1.

Share this post


Link to post
Share on other sites
The java.lang.Class.forName(String className) method will load classes for you and return java.lang.Class objects. To instantiate objects from those classes you just call the newInstance() method on them. This should all work fine if your classes are stored in .class files located in your class path. If you want to load classes in other non-standard ways, you might have to write your own class loader.

Share this post


Link to post
Share on other sites
Thanks

Does java have a method similar to C''s system() function? If it does, I might try using javac while the game is running.

Share this post


Link to post
Share on other sites
From java.lang.Runtime

    
Runtime r=Runtime.getRuntime();
//dont forget to put the full path in the exec string

Process p=r.exec("javac MyClass.java");
try {
//wait for the process to end so you don't try to

//load the class before it is compiled

p.waitFor();
}
catch (InterrupetedException e) {
System.out.println("exception:"+e);
}
//EDIT: don't forget to check that it compiled correctly

if(p.exitValue()==0) {
//load the class

}

You can then use java.lang.ClassLoader to load the class.

---
Make it work.
Make it fast.

"Commmmpuuuuterrrr.." --Scotty Star Trek IV:The Voyage Home

Edited by - CaptainJester on February 7, 2002 9:24:03 AM

Share this post


Link to post
Share on other sites
Why create your own scripting language when there''s already a good one out there?

www.jython.org

sites about scripting languages that run in a JVM
http://www.byte.com/documents/s=505/BYT20001214S0006/
http://www.ociweb.com/jnb/archive/jnbMar2001.html
http://www.mindview.net/Books/TIPatterns/index_html

Share this post


Link to post
Share on other sites
I did consider using jython, but it doesn''t seem to be very well documented, and my attempt at embedding it failed miserably.

How do you access an java object within a python script?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Instead of calling a system javac, you could also use a java compiler written in java ! IIRC there was one on sourceforge, but can''t remember the name :/

Share this post


Link to post
Share on other sites
I think BeanShell can be used for scripting. Not sure how it works though.

Share this post


Link to post
Share on other sites