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