[英]Effective Use of Java Reflection - is this a hack, or is this standard practice?
嘿,长时间听众第一次打电话,我问一个与Java反射相关的问题,以及它是多么容易让自己看起来很丑陋的编码。 下面的方法尝试获取两个相似的对象(一个对象具有另一个对象的所有字段,然后是一些对象),并将它们中的两个进行比较以获得相等性。 如果对象共享的getter相等,它将(据称)返回true,如果它们不相等则返回false。
public boolean validateArchive( Object record, Object arcRecord ) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
{
log.debug( record.getClass().toString() );
Object methodValue;
Object arcMethodValue;
for ( Method method : record.getClass().getMethods() )
{
if ( method.getTypeParameters().length == 0 && method.getName().startsWith( "get" ) && !method.getName().startsWith( "getClass" ) )
{
methodValue = method.invoke( record );
arcMethodValue = arcRecord.getClass().getMethod( method.getName() ).invoke( arcRecord );
log.debug( "Method name: " + method.getName() );
log.debug( "Archive value: " + arcMethodValue );
log.debug( "Object value: " + methodValue );
if ( arcMethodValue != null && methodValue != null && !arcMethodValue.equals( methodValue ) )
{
return false;
}
else
{
if ( arcMethodValue == null && methodValue != null || methodValue == null && arcMethodValue != null )
{
return false;
}
}
}
}
return true;
}
这个方法做了我期望它在单元测试中做的事情,但它看起来很难看,并且感觉不对(我特别不喜欢嵌套'if'的粉丝)。 我只是希望能有一些关于如何更有效/更有效地做到这一点的指示。 如果我违反了某种发布规则,请随时纠正我,我渴望学习等等。
对于此特定任务,我建议在要比较的类中实现equals方法,除非您没有该选项(例如,如果您没有原始类的源代码)。 像IntelliJ这样的IDE提供了对“equals”和“hashcode”方法创建的支持(在IntelliJ中,您提供了将要比较的字段以及哪些字段可以为null或不为null)。 对于这个特殊情况,我会说使用这些工具。
有一种情况我认为使用Reflection的实现会很有用 - 在单元测试中,如果你想在相等不成立时抛出一个断言错误,你实际上可以为失败的确切字段抛出一个断言,并且不只是一个通用的“对象不一样”的断言错误 - 即使在这种情况下,我会在我的原始验证之后执行一个等于确保对象是相同的,或者至少是equals方法的实现和好好工作。
PS:如果你想摆脱所有这些编码检查Beans Common库; PS 2:反射也不错,它可以在任何没有显式代码调用的地方使用 - 例如Spring配置文件。 只是不要滥用它。
因为你只关注“属性”,你可以使用commons beanutils ,更确切地说是这个类 ......
(我猜你不能实现.equals,因为你的对象不共享相同的类型......)
我相信你正在if
语句中测试不必要的情况,并且可以将它们减少到这个:
if ( arcMethodValue == null ) {
if ( methodValue != null) {
return false;
}
} else if ( !arcMethodValue.equals( methodValue ) ) {
return false;
}
此外,您正在调用method.getName()
4次,您可以创建一个变量然后使用它。
您的返回代码不必要地复杂化。 用于比较参考类型的标准习语是:
(field1 == null) ? (field2 == null) : field1.equals(field2);
这更加清晰,非常标准(Effective Java第2版,第43页)。
更新:
从早些时候我写过return [idiom]
就有一种混乱。 是的,在这种情况下, return
不会是原始海报想要的。 他想要if ![idiom] return false;
代替。 我的观点是[idiom]
有效,而且好多了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.