从带反射的解析字符串中获取正确的方法



我做了一个通用类,以对象为输入并实现一个方法,该方法给定该对象的方法及其参数之一的字符串表示(即"charAt(3)"),进行解析并找到并擦出正确的方法。我能够使它运行没有参数的方法,但由于我不理解的原因,它在其他一些方法上失败(如字符串的charAt)。代码如下:

public class MiniInterpreter<T> 
{
private Class<?> objClass;
private T object;
public MiniInterprete(T object)
{
    objClass = object.getClass();
    this.object = object;
}
private static boolean isNumeric(String str)  
{  
  try  
  {  
    @SuppressWarnings("unused")
    int i = Integer.parseInt(str);  
  }  
  catch(NumberFormatException nfe)  
  {  
    return false;  
  }  
  return true;  
}
private static boolean isBoolean(String str)
{
    return (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false"));
}

private static boolean isDouble(String str)
{
    try
    {
        @SuppressWarnings("unused")
        double d = Double.parseDouble(str);
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
    return true;
}
public String getName(int index, String str)
{
    if(str.charAt(index) == '(' || str.charAt(index) == ')')
        return "";
    else
        return str.charAt(index) + getName(index + 1, str);
}
public String getParameters(int index, String str)
{
        switch(str.charAt(index))
        {
        case '(': return "" + getName(index + 1, str);
        default: return getParametri(index + 1, str);
        }
}
public Object parse(String method) throws GenericErrorException
{
    String name = getName(0,method);
    String parameters = getParameters(0,method);
    if(!parameters.equals(""))
    {
        return parseParameters(name, parameters.split(","));
    }
    Method m = null;
    try 
    {
        m = objClass.getMethod(name);
    } 
    catch (NoSuchMethodException e) {e.printStackTrace();} 
    catch (SecurityException e) {e.printStackTrace();}
    try 
    {
        return m.invoke(object);
    } 
    catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {throw new GenericErrorException();}
}
private Object parseParameters(String name, String[] parameters) throws GenericErrorException
{
    List<Class<?>> parametersList = new ArrayList<Class<?>>();
    List<Object> parametersArray = new ArrayList<Object>();
    for(String s : parameters)
    {
        Object obj = null;
        if(isNumeric(s))
        {
            obj = Integer.parseInt(s);
        }
        else if(isDouble(s))
        {
            obj = Double.parseDouble(s);
        }
        else if(isBoolean(s))
        {
            obj = Boolean.parseBoolean(s);
        }
        else
            obj = s;
        parametersList.add(obj.getClass());
        parametersArray.add(obj);
    }
    Method m = null;
    Class<?>[] parametersTypeArray = parametersList.toArray(new Class<?>[parametersList.size()]);
    try 
    {
            m = objClass.getMethod(name, parametersTypeArray );
    } 
    catch (NoSuchMethodException | SecurityException e) {e.printStackTrace();}
    try 
    {
        return m.invoke(object, parametersArray.toArray());
    } 
    catch (IllegalAccessException | IllegalArgumentException
            | InvocationTargetException e) {throw new GenericErrorException();}
}
}

唯一允许的类型是String,Integer,Boolean和Double,这对于方法来说也是正确的,我还必须假装没有超过一个具有该名称和参数的方法,我只是想知道我是否忽略了一些东西,或者如果代码因为这个限制而不能正常工作。当它不起作用时,我得到noSuchMethod异常,当然,nullPointer一个原因是它没有初始化方法。

正如user1676075所建议的,您的问题是您正在寻找一个不存在的方法,因为您的签名错误。

String#charAt(int)是你给的例子。签名为原始类型int,与Integer类不同。你使用

obj = Integer.parseInt(s)

返回一个int类型,所以您可能认为您得到了一个原语。但是你不能在对象中存储原语,Java知道这一点。由于objObject, Java自动将原语int装箱为Integer。然后你请求一个名称为charAt,签名为Integer的方法,JRE说它从未听说过这个方法。

如果您满足于只使用接受int的方法,而忽略任何接受Integer的方法(这将覆盖大多数标准库),您可以指定类型:

obj = Integer.parseInt(s);
parametersList.add(Integer.TYPE);  // the type of primitive ints
然而,如果你想正确地完成它,你就需要让你的代码更复杂。我不调用Class#getMethod(),而是调用Class#getDeclaredMethods(),找到那些具有您正在寻找的名称的子集,然后查看方法的参数列表是否与您的参数类型兼容。

添加.class修复程序在所有公共方法上运行顺利,错误是在私有方法parseParameters中,甚至没有必要为两种不同的情况(解析带有参数的字符串或empty())创建第二个方法,给getMethod一个空列表将得到正确的结果,无论如何,感谢您的支持。

for(String s : parameters)
    {
        if(isNumeric(s))
        {
            parametersList.add(int.class);
            parametersArray.add(Integer.parseInt(s));
        }
        else if(isDouble(s))
        {
            parametersList.add(double.class);
            parametersArray.add(Double.parseDouble(s));
        }
        else if(isBoolean(s))
        {
            parametersList.add(boolean.class);
            parametersArray.add(Boolean.parseBoolean(s));
        }
        else
        {
            parametersList.add(s.getClass());
            parametersArray.add(s);
        }

相关内容

  • 没有找到相关文章

最新更新