我做了一个通用类,以对象为输入并实现一个方法,该方法给定该对象的方法及其参数之一的字符串表示(即"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知道这一点。由于obj
是Object
, 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);
}