Java中的函數動態調用

來源:互聯網
上載者:User

//------------------------------------- 
//類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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.