簡體   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