2013-05-17 25 views
1

如何重新创建方法调用?当我得到的是方法列表,由getDeclaredMethods()获得,并转换为HashMap<String,Method>和其参数的类列表,由getParameterTypes()获得。重新创建方法调用(使用反射)

假设我从用户得到一个字符串,我想调用它:

"print(3,"Hello World!",true,2.4f)" 

而且方法print(int,String,boolean,float)是中的getMethods部分()阵列。我很难弄清楚如何撰写调用。到目前为止,这是我得到:

private static final Pattern functionCall = Pattern.compile(String.format("^%s\\(%s?\\)$", "(\\w+)", "(.*)")); 

if((m = functionCall.matcher(line)).find()) { 
    String function = m.group(1); // in this example = "print" 
    String arguments = m.group(2); // in this example = "3,\\"Hello World!\\",true,2.4f" 
    if(methods.containsKey(function)) { 
     Method method = methods.get(function); 
     Class<?>[] paramsExpected = method.getParameterTypes(); 
     String [] paramsActual = arguments.split(","); 
     if(paramsExpected.length != paramsActual.length) { 
      throw new IllegalArgumentException(function + ": bad number of arguments"); 
     } 
     for(Class<?> param: paramsExpected) { 
      ??????? 
     } 
     method.invoke(context, ??????); 

要非常清楚,我不知道用户预先将输入的,我有什么字符串来检查它,可用的方法和参数,如果我找到它,然后我必须用用户提供的参数调用它。

回答

2

这是你需要做的。一种选择是使用BeanUtils的ConverterUtils.convert方法将字符串转换为特定类型的对象。这将适用于内置类型。

Object[] args = new Object[paramsExpected.length]; 
    int i = 0; 
    for(Class<?> param: paramsExpected) { 
     args[i] = convertStringToType(paramsActual[i], param); 
     i = i +1; 
    } 
    method.invoke(context, args); 

    Object convertStringToType(String input, Class<?> type) { 
     return ConverterUtils.convert(input,type); 
    } 
+0

这绝对是一步。我看了一下你提供的链接,不清楚它是如何处理像int,boolean等基元的。看起来它只是转换对象。 'convert(Class type,Object value)将指定的输入对象转换为指定类型的输出对象。“(当然,您忘记增加'i',但那很小) – ilomambo

+0

反射api不区分基本和对象包装。即使是原语也被转换为它们的等价包装类型。您可以通过打印每个参数的类名来验证。 – gkamal

+1

我想我会部分地用你自己的答案转换参数,使用'param.getSimpleName()'或'param.getCanonicalName()'然后应用合适的'valueOf()' – ilomambo