相 信 有 不 少 人 使 用C 语 言 的 函 数 指 针 实 现 过 函 数 的 动 态 调 用。 适 当 地 运 用 函 数 动 态 调 用 功 能 不 仅 能 减 少 代 码 数 量, 而 且 对 于 增 加 程 序 的 可 读 性 和 易 维 护 性 也 带 来 极 大 帮 助。 由 于java 不 支 持 指 针 功 能, 所 以 运 用 指 针 实 现 动 态 调 用 不 适 用 于java。 本 文 提 出 了 一 种 运 用java Reflection API 实 现java 函 数 动 态 调 用 的 方 法, 并 给 出 一 个 基 本 实 现 和 测 试 实 例。
---- 函 数 动 态 调 用 的 一 个 最 为 常 见 的 应 用 场 合 在 于 取 消 对 于switch 关 键 词 的 依 赖。switch 关 键 词 用 来 判 断 条 件, 并 分 别 给 出 处 理 过 程 即 处 理 函 数。 一 个 典 型 的 函 数 具 有 函 数 名、 输 入 值、 返 回 值。 而 实 现 动 态 调 用 的 关 键 之 处 在 于 调 用 时 得 到 正 确 的 类 名、 函 数( 方 法) 名、 以 统 一 的 格 式 实 现 参 数 的 传 递。 下 面 是 实 现 该 功 能 的 类Invoker,ArgumentHolder 的 清 单:
//--------------------------------------
//类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()));
}
}
//-------------------------------------
//类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 =