Java 将未知对象转换为适当方法的有效方法。调用参数?

Java 将未知对象转换为适当方法的有效方法。调用参数?,java,reflection,Java,Reflection,我正在编写一个基于反射的RPC服务,它通过各种机制传递参数。有时参数与参数类型正确匹配,有时它们总是字符串,有时它们被封装在需要提取适当值的动态类型“脚本”对象中 在调用method.invoke之前,我需要构建参数列表,如下所示: Object a[] = new Object[method.parameterClasses.length]; for (int i = 0; i < a.length; ++i) { a[i] = prepare(method.parameterCl

我正在编写一个基于反射的RPC服务,它通过各种机制传递参数。有时参数与参数类型正确匹配,有时它们总是字符串,有时它们被封装在需要提取适当值的动态类型“脚本”对象中

在调用method.invoke之前,我需要构建参数列表,如下所示:

Object a[] = new Object[method.parameterClasses.length];
for (int i = 0; i < a.length; ++i)
{
   a[i] = prepare(method.parameterClasses[i], rpc.arguments[i]);
}
在单元测试期间,我最近相当惊讶地发现,一个方法传递了一个装箱整数,该整数期望一个原语long,但实际上未能通过强制转换并从底部掉落,然后在invoke()期间被某些东西正确转换。我以为叫“演员”就行了。是否有任何方法可以显式执行和检查由invoke正常完成的参数转换

缺少这些,我考虑对数字类型进行显式检查,但排列的数量似乎已经无法控制了。当我添加对从脚本动态类型提取数字和转换字符串的支持时,情况会变得更糟。我设想对每个可能的数字目标类进行一系列条件类型检查,字符串参数为Integer.decode、Long.decode等,数字参数为Short.decode、Number.intValue、Number.longValue等


有没有更好的方法来完成这一切?一开始这似乎是个不错的方法,但现在越来越恶心。

真的没有更好的方法了。有无限多的潜在转换,但只有一小部分真正有意义。我建议为类型强制指定一个契约,而不是试图给客户端完全的自由


首先,请查看所使用的类型转换规则。这些规则功能强大,允许进行多种类型的转换,但它们定义良好,易于记忆,易于实现。

至少可以使用一些快捷方式来简化代码:

  • 如果参数是java.lang.Number的实例,并且参数类型为byte、short、int、long、float或double(作为原语或包装类),则可以使用Number中的方法(如byteValue()、shortValue()等)转换参数

  • 如果参数是java.lang.String的实例,并且参数类型是上述类型之一,则可以在相应的类中使用static valueOf(String)方法进行转换


进一步转换,甚至可能是专有类型,当然需要更多的工作。如果它真的是必要的,并且您的准备方法正在变得越来越大,您可能应该考虑抽象接口背后的转换,并允许可插入的转换提供程序动态地添加到应用程序中。

确实令人惊讶,但这是当前的行为。见小虫


就解决问题的更好方法而言,在其核心,不,你必须定义所有这些规则。不过,有一些更好的(更易于维护的)模式比一系列if更好。首先,我有一些策略对象,可以为这些对象的一侧(可能是类一侧)调用,这样您就可以根据类查找适当的对象(比如从映射中),然后您可以将转换限制在一侧(每个对象都关心如何将内容放入特定的类)。这样,当您需要支持一种新的类转换时,您可以为它编写一个对象,单独测试它,并将其插入映射,而无需进一步更改代码。

我的目标是受约束的合理转换,但我认为数字类型是一个应该尽可能灵活的领域,而仅仅是管理这些就失去了控制!顺便说一句,谢谢你的想法。。。我在看JSPEL规则。。果然,这是一个很长很烦人的条件转换列表。唉。哦,好吧,我可能可以在我打这个问题的时候写出来。:-)
Object prepare(Class clazz, Object o)
{
   if (o == null) return null;
   if (clazz == o.getClass()) return o;
   if (clazz == String.class) return o.toString();

   // skip a bunch of stuff for converting strings to dates and whatnot

   // skip a bunch of stuff for converting dynamic types

   // final attempts:
   try
   {
       return clazz.cast(o);
   }
   catch (Exception e)
   {
       return o;     // I give up.  Try the invoke and hope for the best!
   }


}