将未知对象转换为适当的Method.invoke参数的有效方法?
我正在写一个基于反射的RPC服务,它通过各种机制获取传入的参数。有时参数与参数类型正确匹配,有时候它们总是字符串,有时它们会被包含在动态类型的“脚本”对象中,这些对象需要提取出适当的值。将未知对象转换为适当的Method.invoke参数的有效方法?
之前,我可以打电话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]);
}
“准备”的方法看起来像是:
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!
}
}
在单元测试,我最近很惊讶地发现一个方法通过了一个盒装Integer,期望一个原始的长实际上是失败的演员,并通过底部,然后在invoke()期间正确转换的东西。我认为打电话给“演员”是可以做到的。有没有什么办法显式地执行和检查通常由invoke完成的参数转换?
缺乏这一点,我想过对数字类型进行明确的检查,但排列的数量似乎无法实现。当我添加从脚本动态类型提取数字和转换字符串的支持时,情况会变得更糟。我为每个可能的数字目标类设想了一系列条件类型检查,其中Integer.decode,Long.decode等用于Numbers的String参数,Short.decode和Number.intValue,Number.longValue等。
有没有更好的方法来做这件事?起初它似乎是一个很好的方法,但它变得相当糟糕。
确实令人惊讶,但这是目前的行为。查看错误6456930。
在一个更好的办法来解决这个问题方面,其核心是不,你必须定义所有的这些规则。尽管如此,有一系列更好(更可维护)的模式。对于初学者来说,我会为这些对象的一边(可能是类边)调用一些策略对象,以便根据类查找适当的对象(比如来自Map),然后可以限制你转换到一边(每个对象都会关心如何将事物放入特定的类)。这样,当你需要支持一种新的类转换时,你可以为它编写一个对象,单独测试它,并将其插入到地图中,而无需更改代码。
确实没有更好的方法。有无数的潜在转化,但只有一小部分是真正有意义的。我不建议为客户提供完全的自由,而是建议指定类型强制合同。
作为一个起点,请查看JSP Expression Language.使用的类型转换规则它们非常强大,允许进行多种类型的转换,但它们也定义明确,易于记忆,并且可以实现。
有您可以采取简化代码至少有几个快捷键:
如果参数是java.lang.Number中的一个实例和参数类型为字节,short,int和long,float或者double(或者作为primitive或者wrapper类),你可以使用Number中的方法如byteValue(),shortValue()等来转换参数。
如果参数是java.lang.String的一个实例并且参数类型是上面提到的参数类型之一,那么可以在相应的类中使用静态valueOf(String)方法进行转换。
进一步转换,甚至私有类型当然需要更多的工作。如果真的有必要,而且您的准备方法越来越大,那么您可能应该考虑抽象化接口背后的转换,并允许可插入的转换提供程序动态添加到应用程序中?
约束合理的转换是我的目标,但我要说的却是数字类型是一个区域,它应该是尽可能的灵活,只是管理这些是失控! – 2009-09-29 19:43:08
顺便说一句,谢谢你的想法......我正在看JSPEL规则..当然,这是一个很长的烦人的条件转换列表。叹。哦,我可能可以在写下这个问题的时候写下它。 :-) – 2009-09-29 19:47:50