Java中的函数动态调用

来源:互联网 发布:淘宝上架新品不显示 编辑:程序博客网 时间:2024/06/05 16:13

//------------------------------------- 
//类ArgumentHolder 
//用于调用参数的封装,实现变长参数及 
//不同类型参数的统一形式地传递 
//成员变量: 
// Class[] cl 参数类型数组 
// Object[] args 参数对象数组 
//方法: 
// getArgumentClasses()返回参数类型数组 
// getArguments() 返回参数对象数组 
// setArgument() 在参数列表中增加项目 
// 
//--------------------------------------- 
public class ArgumentHolder {
 protected Class[] cl; 
 protected Object[] args; 
 protected int argc; 
 
 ArgumentHolder() { 
  argc = 0; 
  cl = new Class[0]; 
  args = new Object[0]; 
 } 
 ArgumentHolder(int argc) { 
  this.argc = argc; 
  cl = new Class[argc]; 
  args = new Object[argc]; 
 } 
 
 public Class[] getArgumentClasses() { 
  return cl; 
 } 
 public Object[] getArguments() { 
  return args; 
 } 
 
 //以下16个setArgument 
 //函数实现简单数据类型boolean,byte, 
 // char,int,short,long,float,double的封装。 
 //为支持Invoker 
 //类dynaCall方法中getClass的调用, 
 //此处将简单数据类型 
 //转换为对应的对象,如boolean转换为Boolean 
 public int setArgument(boolean b) { 
  return this.setArgument(argc, new Boolean(b), 
  Boolean.TYPE); 
 } 
 public int setArgument(int argnum, boolean b) {
  return this.setArgument(argnum, new Boolean(b),Boolean.TYPE); 
 } 
 public int setArgument(byte b) { 
  return this.setArgument(argc, new Byte(b),Byte.TYPE); 
 } 
 
 public int setArgument(int argnum, byte b) { 
  return this.setArgument(argnum, new Byte(b),Byte.TYPE); 
 } 
 public int setArgument(char c) { 
  return this.setArgument(argc, new Character(c),Character.TYPE); 
 } 
 public int setArgument(int argnum, char c) { 
  return this.setArgument(argnum, new Character(c),Character.TYPE); 
 } 
 public int setArgument(int i) { 
  return this.setArgument(argc, new Integer(i),Integer.TYPE); 
 } 
 public int setArgument(int argnum, int i) { 
  return this.setArgument(argnum, new Integer(i), Integer.TYPE); 
 } 
 public int setArgument(short s) { 
  return this.setArgument(argc, new Short(s),Short.TYPE); 
 } 
 public int setArgument(int argnum, short s) { 
  return this.setArgument(argnum, new Short(s),Short.TYPE); 
 } 
 public int setArgument(long l) { 
 return this.setArgument(argc, new Long(l),Long.TYPE); 
 } 
 public int setArgument(int argnum, long l) { 
  return this.setArgument(argnum, new Long(l),Long.TYPE); 
 } 
 public int setArgument(float f) { 
  return this.setArgument(argc, new Float(f),Float.TYPE); 
 } 
 public int setArgument(int argnum, float f) { 
 return this.setArgument(argnum, new Float(f), 
 Float.TYPE); 
 } 
 public int setArgument(double d) { 
  return this.setArgument(argc, new Double(d),Double.TYPE); 
 } 
 public int setArgument(int argnum, double d) { 
  return this.setArgument(argnum, new Double(d),Double.TYPE); 
 } 
 
 //以下2个setArgument函数实现对象的封装, 
 public int setArgument(Object obj) { 
  return this.setArgument(argc, obj, 
  obj.getClass()); 
 } 
 public int setArgument(int argnum, Object obj) { 
  return this.setArgument(argnum, obj, 
  obj.getClass()); 
 } 
 
 //以下setArgument函数具体实现以对象形式 
 //提供的参数封装。 
 //具体操作为:增加计数器argc的值、 
 //在cl和args中增加相应内容 
 public int setArgument(int argnum,Object obj, Class c) { 
  if (argnum >= args.length) { 
   argc = argnum + 1; 
   Class[] clExpanded = new Class[argc]; 
   Object[] argsExpanded = new Object[argc]; 
   System.arraycopy(cl, 0, clExpanded, 
   0, cl.length); 
   System.arraycopy(args, 0, argsExpanded, 
   0, args.length); 
   cl = clExpanded; 
   args = argsExpanded; 
  } 
  args[argnum] = obj; 
  cl[argnum] = c; 
  return argnum; 
 } 

//
//---- 以 下 给 出 一 个 类Invoker 和ArgumentHolder 的 应 用 实 例。 
//类DynaCallTest 应 用 类Invoker 和ArgumentHolder 实 现 以 下 功 能: 根 据 用 户 在 命 令 行 中 输 入 的 内 容, 动 态 地 确 定 所 调 用 方 法。 程 序 可 以 接 受 的 合 法 输 入 为: 
//
//add 参数为两个整数,显示两个整数之和 
//concat 参数为两个字符串,显示两个字符串连接之后的值 
//help 无参数,显示可以接受的命令列表 
//minmax 参数为三个整数,显示三个参数的最大之和最小值 
//quit 无参数,结束运行 
//rand 无参数,显示一个随机值 
//
//程序清单如下: 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.Random;
import java.util.StringTokenizer;

public class DynaCallTest { 
 
 Random rand; 
 BufferedReader consoleIn; 
 
 //建构函数,初始化 
 DynaCallTest() { 
  consoleIn = new BufferedReader 
  (new InputStreamReader(System.in)); 
  rand = new Random(); 
 } 
 //读取用户输入行 
 String getCommandLine() throws IOException { 
  System.out.print(">"); 
  System.out.flush(); 
  String commandLine = consoleIn.readLine(); 
  if (commandLine == null) 
  return "Quit"; 
  if (commandLine.length() == 0) 
  return "Quit"; 
  else 
  return commandLine; 
 } 
 
  //从用户输入行中提取命令, 
  //格式化为:首字符大写,其余字符小写 
  //返回格式化后的命令 
  String extractCommand(String commandLine) { 
   StringTokenizer t = new StringTokenizer(commandLine); 
   String cmd = t.nextToken().toLowerCase(); 
   return cmd.substring(0,1).toUpperCase() 
   + cmd.substring(1); 
 } 
 
 //从用户输入行中提取参数, 
 //创建ArgumentHolder类型的对象a以封装所有参数 
 //错误格式的整数被视为字符串 
 //返回ArgumentHolder类型的对象,即封装后的参数 
 ArgumentHolder extractArguments(String cmd) { 
  StringTokenizer t = new StringTokenizer(cmd); 
  int tokenCount = t.countTokens(); 
  ArgumentHolder a = new ArgumentHolder(); 
  String token = t.nextToken(); 
  while(t.hasMoreTokens()) { 
   token = t.nextToken(); 
   try { 
    int i = Integer.parseInt(token); 
    a.setArgument(i); 
   } 
   catch (NumberFormatException e) { 
    a.setArgument(token); 
   } 
  } 
  return a; 
 } 
 
 //以下6个以meth开头的函数实现本测试程序 
 //接受的合法命令的具体处理过程。 
 //函数的命名规则为:meth+格式化后的用户命令 
 public String methAdd(int i1, int i2) { 
  return Integer.toString(i1) + " + " + 
  Integer.toString(i2) + " = " + Integer.toString(i1 + i2); 
 } 
 public String methConcat(String s1, String s2) { 
  return "the concatenated string is " + s1 + s2; 
 } 
 public String methHelp() { 
  final String[] helpMessages = 
  {"DynaCallTest Version 1.0", 
  "valid commands are:", 
  "add int1 int2", 
  "concat string1 string 2", 
  "help", 
  "minmax int1 int2 int3", 
  "quit", 
  "rand" 
  }; 
  for (int i = 0; i < helpMessages.length; ++i) 
  System.out.println(helpMessages[i]); 
  return ""; 
 } 
 public String methMinmax(int i1, int i2, int i3) { 
  return ("min = " + 
  Integer.toString(java.lang.Math.min 
  (java.lang.Math.min( 
  i1,i2),i3)) + ", max = " + Integer.toString( 
  java.lang.Math.max(java.lang.Math.max(i1,i2),i3))); 
 } 
 public String methQuit() { 
  return "quitting"; 
 } 
 public String methRand() { 
  return "the random number is " 
  + Integer.toString(rand.nextInt()); 
 } 
 
 //处理用户在命令行中的输入 
 //调用extractCommand以生成对应于用户输入的方法名 
 //调用extractArguments以封装用户输入参数 
 //调用Invoker.dynaCall以实现命令处理 
 String processCommand(String cmd) { 
  try { 
   String meth = "meth" + extractCommand(cmd); 
   ArgumentHolder a = extractArguments(cmd); 
   return (String)(Invoker.dynaCall(this, meth,a)); 
  } 
  catch (NoSuchMethodException e) { 
   return "no method to process command " + cmd; 
  } 
  catch (InvocationTargetException e) { 
   System.out.println("trace:"); 
   e.printStackTrace(); 
   return "InvocationTargetException processing command" + cmd; 
  } 
  catch (IllegalAccessException e) { 
   System.out.println("trace:"); 
   e.printStackTrace(); 
   return "IllegalAccessException processing command" + cmd; 
  } 
 } 
 
 //主函数,调用processCommand以实现程序功能 
 public static void main(String args[]) { 
  boolean allOK = true; 
  String line; 
  
  DynaCallTest myClient = new DynaCallTest(); 
  
  System.out.println("DynaCallTest Version 1.0"); 
  System.out.println("Enter command at the prompt"); 
  System.out.println("Type help for help"); 
  while(allOK) { 
   try { 
    line = myClient.getCommandLine(); 
    if (line == null) 
     allOK = false; 
    else { 
     System.out.println(myClient.processCommand(line)); 
     if (line.substring(0,1).toUpperCase().equals("Q")) 
     allOK = false; 
    } 
   } 
   catch (IOException e) { 
    e.printStackTrace(); 
    allOK = false; 
   } 
  } 
  System.exit(0); 
 } 
}

//-------------------------------------- 
//类Invoker 
//实现函数的动态调用 
//方法: 
// dynaCall 
// 参数 Object c希望调用函数(方法)所在对象 
// String m希望调用的方法名称 
// ArgumentHolder a传递给被调用方法的参数 
//----------------------------------------- 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Invoker {
 static Object dynaCall(Object c,String m, 
      ArgumentHolder a) throws NoSuchMethodException,InvocationTargetException,IllegalAccessException { 
 
 //由于java支持方法名称的重载 
 //(同一类中出现多于一个的同名函数), 
 //所以getMethod方法使用两个参数: 
 //字符串形式的方法名称和数组形式 
 //的调用参数类列表。返回值为类Method的一个对象, 
 //该对象和将要被 
 //调用的方法相关联 
 Method meth = c.getClass().getMethod(m, a.getArgumentClasses()); 
 
 //通过类Method对象的invoke方法动态调用希望调用的方法 
 return (meth.invoke(c, a.getArguments()));
 }
}

 

 

文章来源:http://www.cn-java.com/www1/?action-viewnews-itemid-2317