值得一提的是,大多数脚本语言(如Perl)和非静态编译时语言(如Pick)都支持自动运行时动态String到(相对任意)对象转换。这也可以用Java来完成,而又不会丢失类型安全性,而静态类型化语言的优点就不会给其他一些用动态转换造成邪恶的语言带来讨厌的副作用。一个执行一些可疑数学的Perl示例:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
在Java中,使用我称为“交叉广播”的方法可以更好地实现(IMHO)。通过交叉广播,反射可用于通过以下静态方法动态发现的构造函数和方法的延迟加载缓存中:
Object fromString (String value, Class targetClass)
不幸的是,对于从String到BigDecimal或从String到Integer或任何其他不支持类层次结构的转换,没有内置的Java方法(如Class.cast())会执行此操作。就我而言,重点是提供一种完全动态的方法来实现此目的-我认为先前的参考文献不是正确的方法-必须对每次转换进行编码。简而言之,如果合法/可行,则实现只是从字符串强制转换。
因此,解决方案是简单的反思,寻找以下任一个的公共成员:
STRING_CLASS_ARRAY =(新类[] {String.class});
a)成员成员= targetClass.getMethod(method.getName(),STRING_CLASS_ARRAY); b)成员成员= targetClass.getConstructor(STRING_CLASS_ARRAY);
您会发现此方法涵盖了所有原语(Integer,Long等)以及所有基础知识(BigInteger,BigDecimal等),甚至java.regex.Pattern。我在生产项目中使用了此方法,并取得了巨大的成功,在生产项目中,大量的任意String值输入需要进行更严格的检查。在这种方法中,如果没有方法或调用该方法,则将引发异常(因为这是非法值,例如BigDecimal的非数字输入或Pattern的非法RegEx),它提供了特定于目标类固有的逻辑。
这有一些缺点:
1)您需要很好地理解反射(这有点复杂,不适合新手使用)。2)(某些)Java类以及实际上第3方库未正确编码。也就是说,有些方法将单个字符串参数作为输入并返回目标类的实例,但这不是您想的...考虑Integer类:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
上面的方法与包装原始整型int的对象确实没有任何关系。反射会认为这可能是错误地根据String与解码,valueof和构造函数成员而不是Integer创建整数的可能候选者-它们都适合于大多数任意String转换,在这些转换中您实际上无法控制输入数据,而只想知道是否有可能是整数。
为了解决上述问题,寻找引发Exception的方法是一个很好的开始,因为创建此类对象实例的无效输入值应引发Exception。不幸的是,关于是否将异常声明为选中状态,实现方式有所不同。例如,Integer.valueOf(String)抛出一个已检查的NumberFormatException,但是在反射查找期间找不到Pattern.compile()异常。同样,我认为这种动态的“交叉广播”方法并不是失败,这与对象创建方法中异常声明的非常非标准实现一样。
如果有人想了解有关上述实现方式的更多详细信息,请告诉我,但我认为该解决方案更加灵活/可扩展,并且代码更少,而不会丢失类型安全性的优点。当然,“了解您的数据”始终是最好的选择,但是正如我们许多人所发现的那样,有时我们只是非托管内容的接收者,因此必须尽我们所能来正确使用它。
干杯。