Java 从带有反射的已解析字符串中获取正确的方法
我已经创建了一个泛型类,它以一个对象作为输入,并实现了一个方法,该方法给定该对象的一个方法及其参数的字符串表示形式(即“charAt(3)”),从而进行解析并找到正确的方法。 我能够让它为没有参数的方法运行,但原因是我不明白,在其他一些方法上(比如字符串的charAt)不断失败。 这是密码Java 从带有反射的已解析字符串中获取正确的方法,java,parsing,reflection,Java,Parsing,Reflection,我已经创建了一个泛型类,它以一个对象作为输入,并实现了一个方法,该方法给定该对象的一个方法及其参数的字符串表示形式(即“charAt(3)”),从而进行解析并找到正确的方法。 我能够让它为没有参数的方法运行,但原因是我不明白,在其他一些方法上(比如字符串的charAt)不断失败。 这是密码 public class MiniInterpreter<T> { private Class<?> objClass; private T object; public Mini
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();}
}
}
公共类小型解释器
{
私有类对象类;
私人T对象;
公共小型解释器(T对象)
{
objClass=object.getClass();
this.object=对象;
}
私有静态布尔值isNumeric(字符串str)
{
尝试
{
@抑制警告(“未使用”)
int i=Integer.parseInt(str);
}
捕获(NumberFormatException nfe)
{
返回false;
}
返回true;
}
私有静态布尔值isBoolean(字符串str)
{
返回(str.equalsIgnoreCase(“真”)| | str.equalsIgnoreCase(“假”);
}
专用静态布尔isDouble(字符串str)
{
尝试
{
@抑制警告(“未使用”)
double d=double.parseDouble(str);
}
捕获(NumberFormatException nfe)
{
返回false;
}
返回true;
}
公共字符串getName(int索引,String str)
{
如果(str.charAt(索引)='('| | str.charAt(索引)='))
返回“”;
其他的
返回str.charAt(index)+getName(index+1,str);
}
公共字符串getParameters(int索引、字符串str)
{
开关(str.charAt(索引))
{
大小写“(”:返回“”+getName(索引+1,str);
默认值:返回getParameteri(索引+1,str);
}
}
公共对象解析(字符串方法)引发GenericErrorException
{
String name=getName(0,方法);
字符串参数=getParameters(0,方法);
如果(!parameters.equals(“”)
{
返回parseParameters(名称,parameters.split(“,”);
}
方法m=null;
尝试
{
m=objClass.getMethod(名称);
}
catch(NoSuchMethodException){e.printStackTrace();}
catch(SecurityException e){e.printStackTrace();}
尝试
{
返回m.invoke(对象);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e){抛出新的GenericeErrorException();}
}
私有对象parseParameters(字符串名称,字符串[]参数)引发GenericeErrorException
{
列表>();
列表参数array=new ArrayList();
用于(字符串s:参数)
{
objectobj=null;
如果(是数字)
{
obj=整数.parseInt(s);
}
否则,如果(是双重的)
{
obj=Double.parseDouble;
}
else if(isBoolean(s))
{
obj=布尔值。解析布尔值;
}
其他的
obj=s;
参数list.add(obj.getClass());
参数array.add(obj);
}
方法m=null;
类[]parametersTypeArray=parametersList.toArray(新类[parametersList.size()]);
尝试
{
m=objClass.getMethod(名称、参数Y);
}
catch(NoSuchMethodException | SecurityException e){e.printStackTrace();}
尝试
{
返回m.invoke(对象,参数array.toArray());
}
捕获(IllegalAccessException | IllegalArgumentException
|InvocationTargetException e){抛出新的GenericeErrorException();}
}
}
唯一允许的类型是String、Integer、Boolean和Double,对于方法来说也是如此,我还必须假设没有多个方法具有该名称和参数,我只是想知道我是否忽略了某些内容,或者代码是否因为这个限制而无法正常工作。
当它不起作用时,我会得到noSuchMethod异常,当然,nullPointer异常会导致它不初始化该方法。正如user1676075所建议的,您的问题是,您正在寻找一个不存在的方法,因为您的签名错误
String#charAt(int)
是您给出的示例。签名是基本类型int
,它与类Integer
不同。您使用的
obj = Integer.parseInt(s)
它返回一个int
类型,因此您可能认为您得到的是一个基元。但是您不能将基元存储在对象中,Java知道这一点。由于obj
是一个对象
,Java自动将基元int
装箱为整数
。然后您需要一个名为charAt
的方法nd签名Integer
,JRE表示从未听说过
如果您只满足于使用采用int
的方法,而忽略任何采用整数的方法(这将涵盖大多数标准库),则可以指定类型:
obj = Integer.parseInt(s);
parametersList.add(Integer.TYPE); // the type of primitive ints
但是,如果您想正确地执行此操作,则需要使代码更加复杂。与其调用Class#getMethod()
,我还不如调用Class#getDeclaredMethods())
,找到具有您要查找的名称的子集,然后查看该方法的参数列表是否与您的参数类型兼容。添加.fix类该程序在所有公共方法上都能平稳运行,错误在私有方法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);
}
您能发布一个实际的字符串和实际的方法签名吗?请记住int和Integer是不同的方法签名。m=objClass.getMethod(name,parametersTypeArray);这是生成错误的行,它在parseParameters中。当输入字符串在方法中没有参数(如长度)时,调用一个私有方法。让我看看是否得到它,自动装箱/取消装箱Let charAt(整数