繁体   English   中英

有效使用Java反射 - 这是一个黑客,还是这种标准做法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM