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