JAVATM MASTER

IntroSpection

Back to Table of Contents

In the Java language, you can dynamically look up a method in a class, find its argument types, and call it. This is the way XML-RPC finds the methods of the remote class that match its given method signature.

Each Object has a getClass() method that returns the Object's Class as a Class Object. For primitive types, the Class Object is the public static TYPE field in their wrapper class, such as Integer.TYPE for int.

Once you have the Class Object, you can get an array of all the methods as an array of Method Objects with getMethods() or you can get a specific Method Object with getMethod(String Name, Class[] parametersTypes). Note that parameterTypes of Integer.getClass() and Integer.TYPE refer to method Parameters Integer or int respectively and they cannot be interchanged.

When you have a Method Object and an array of all the Parameters as a Object array, you can invoke the method. Note that in the case of the invoke method, Object Wrapper types will apply to both primitives and their respective Object Types. Hence, if you have a Parameter type that is an Integer, it will be converted to int if the method signature is int instead of Integer.

Here is a full working example of dynamically looking up a method in an Object and invoking it:

import java.util.*;
import java.lang.reflect.*;


public class IntroSpection {

	Hashtable Targets = null;
	public IntroSpection(){
		Targets = new Hashtable();
	}
	public void addTarget(String Name, Object Target){
		Targets.put(Name, Target);
	}
	public String execute(String Target, String MethodName, Vector Params)
		throws Exception{
		
		Object Targ = Targets.get(Target);
		if (Targ == null) return "Invalid Target";
		Class C = Targ.getClass();
		Class[] CParams = new Class[Params.size()];
		Object[] ObjParams = new Object[Params.size()];
		for (int i=0; i<CParams.length; ++i){
			Object Prm = Params.elementAt(i);
			CParams[i] = Prm instanceof Integer ? Integer.TYPE : Prm.getClass();
			ObjParams[i] = Prm;
		}
		Method TargMethod = C.getMethod(MethodName, CParams);
		Object Ret = TargMethod.invoke(Targ, ObjParams);
		return Ret.toString();
	}
    public static void main (String args[]) throws Exception
    {
        try {
            String Target = args[0];
            String MethodName = args[1];
            Vector Params = new Vector ();
            for (int i=2; i<args.length; i++) try {
                Params.addElement (new Integer (Integer.parseInt (args[i])));
            } catch (NumberFormatException nfx) {
                Params.addElement (args[i]);
            }
            IntroSpection client = new IntroSpection ();
			client.addTarget("Math", new MathTarget());
			client.addTarget("Str", new StringTarget());
            try {
                System.out.println (client.execute (Target, MethodName, Params));
            } catch (Exception ex) {
                System.out.println ("Error: "+ex.toString());
				System.out.print ("Method Signature: "+ MethodName + "(");
				for (int i=0; i<Params.size(); ++i){
					Object P = Params.elementAt(i);
					if (i > 0) System.out.print(", ");
					System.out.print(""+(P instanceof Integer ? "Integer" : "String"));
				}
				System.out.println(")");
            }
        } catch (Exception x) {
            System.out.println (x);
            System.out.println ("Usage: java " +
                                IntroSpection.class.getName() +
                                " <Math | Str> <method> [args]");
            System.out.println ("Arguments are sent as integers or strings.");
        }
    }
	
}
class MathTarget{
	public MathTarget(){ //empty constructor
	}
	public String add(int A, int B){
		return ""+A+" + "+B+" = "+(A + B);
	}
	public String subtract(int A, int B){
		return ""+A+" - "+B+" = "+(A - B);
	}
	public String times(int A, int B){
		return ""+A+" * "+B+" = "+(A * B);
	}
	public String divide(int A, int B){
		return ""+A+" / "+B+" = "+(A / B);
	}
}
class StringTarget{
	public StringTarget(){ //empty constructor
	}
	public String reverse(String S){
		StringBuffer buf = new StringBuffer();
		for (int i=S.length()-1; i >= 0; --i){
			buf.append(S.charAt(i));
		}
		return buf.toString();
	}
	public String order(String A, String B, String C){
		if (A.compareTo(B) <= 0 && A.compareTo(C) <= 0){
			if (B.compareTo(C) <= 0) return A + ", " + B + ", " + C;
			else return A + ", " + C + ", " + B;
		}
		if (B.compareTo(A) <= 0 && B.compareTo(C) <= 0){
			if (A.compareTo(C) <= 0) return B + ", " + A + ", " + C;
			else return B + ", " + C + ", " + A;
		}
		if (A.compareTo(B) <= 0) return C + ", " + A + ", " + B;
		else return C + ", " + B + ", " + A;
	}
	public String order(String A, String B){
		if (A.compareTo(B) <= 0) return A + ", " + B;
		else return B + ", " + A;
	}
}

It you compile the above class you can run it on the command line as:

java IntroSpection Math add 42 306
42 + 306 = 348

java IntroSpection Math subtract 74 21
74 - 21 = 53

java IntroSpection Str reverse JavaMan
naMavaJ

*OracleTM and JavaTM are registered trademarks of Oracle and or its affiliates. Other names may be trademarks of their respective owners.*