0

我创建了一个泛型类,它以对象作为输入并实现一个方法,该方法给出该对象方法之一及其参数(即“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 导致它没有初始化方法。

4

2 回答 2

0

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

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

obj = Integer.parseInt(s)

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

如果您满足于使用采用int并忽略任何采用的方法Integer(这将涵盖大部分标准库),您可以指定类型:

obj = Integer.parseInt(s);
parametersList.add(Integer.TYPE);  // the type of primitive ints

但是,如果您想正确执行此操作,则需要使您的代码更复杂。Class#getMethod()我不会调用 ,而是调用Class#getDeclaredMethods(),找到具有您要查找的名称的子集,然后查看该方法的参数列表是否与您的参数类型兼容。

于 2013-06-01T16:14:00.590 回答
0

添加 .class 修复程序在所有公共方法上运行顺利,错误出现在私有方法 parseParameters 中,甚至没有必要为两种不同的情况(解析带参数的字符串或空())创建第二种方法,无论如何,为 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);
        }
于 2013-06-02T13:31:23.617 回答