2015-04-03 4 views
7

वहाँ इतने पर दो समान प्रश्न हैं वस्तुओं:दीप पुनरावर्ती तुलना (एक बार फिर)

Is there a Java reflection utility to do a deep comparison of two objects?

Deep reflective compare equals

लेकिन, यह हास्यास्पद है, उनमें से कोई भी सवाल का पूरी तरह से सही जवाब देता है।

boolean deepEquals(Object obj1, Object obj2)

अर्थात किसी भी अपवाद फेंकने और इतने पर बिना:

मुझे और अन्य प्रश्न के लेखक क्या वास्तव में चाहते हैं, कुछ पुस्तकालय जो सिर्फ बता देंगे दो वस्तुओं के बराबर या नहीं दिया जाता है में कुछ विधि है।

apache का EqualsBuilder रास्ता नहीं है, क्योंकि इसकी तुलना गहरी तुलना नहीं करती है।

Unitils भी बुरा निर्णय लगता है, क्योंकि इसकी विधि true या false वापस नहीं आती है; यदि तुलना विफल हुई तो यह सिर्फ अपवाद फेंकता है। बेशक, यह इस तरह से इस्तेमाल किया जा सकता है:

Difference difference = ReflectionComparatorFactory.createRefectionComparator(new ReflectionComparatorMode[]{ReflectionComparatorMode.LENIENT_ORDER, ReflectionComparatorMode.IGNORE_DEFAULTS}).getDifference(oldObject, newObject);

लेकिन यह बहुत बदसूरत लगता है, और unitils पुस्तकालय पूरी तरह से बहुत कठिन के लिए आवश्यक उद्देश्यों की तुलना हो रहा है।

इसके अलावा, यह स्पष्ट है कि इस तरह के deepEquals स्वयं को कैसे बनाया जाए, लेकिन यह संभावना नहीं है कि सामान्य रूप से उपयोग की जाने वाली लाइब्रेरी नहीं हैं जिनमें पहले से ही लागू विधि शामिल है। कोई विचार?

+0

रिकर्सिव तुलना तुच्छ नहीं है। 'EqualsBuilder.reflectionEquals' विधि को देखें - यह आपको निर्दिष्ट करता है कि कौन से फ़ील्ड तुलना नहीं करते हैं और विरासत का उपयोग होने पर कक्षा पदानुक्रम के पेड़ में कितनी दूर तक पहुंचने के लिए। अब यदि आपके पास घोंसला वाली वस्तु है जिसे आप प्रतिबिंब का उपयोग करके तुलना करना चाहते हैं, तो आप कैसे बता सकते हैं कि किन क्षेत्रों को अनदेखा करना है? यदि आपको परवाह नहीं है, तो आपको जो चाहिए उसे प्राप्त करने के लिए 'बराबर बिल्डर' कार्यान्वयन को लपेटना आसान है। अन्यथा आपको यह जानने के लिए एनोटेशन या रजिस्ट्री का उपयोग करने की आवश्यकता हो सकती है कि किन वर्गों की तुलना नहीं की जा सकती है। – krzychu

उत्तर

1

जावा 1.7 Objects.deepEquals(Object a, Object b)

है दुर्भाग्य से Unitils के ReflectionAssert वर्ग एक साथ विधि है कि true या false रिटर्न भी नहीं है। आप की कोशिश कर सकते हैं:

https://github.com/jdereg/java-util

जिसका DeepEquals वर्ग DeepEquals.deepEquals(Object a, Object b) और DeepEquals.deepHashCode(Object o) तरीकों जो आप एक बाहरी Comparator या Equivalence में अपने वर्ग के equals और hashCode तरीकों को ओवरराइड या उपयोग करने के लिए उपयोग कर सकते हैं।

नोट: इस DeepEquals कार्यान्वयन की सीमा है। यदि कक्षा में उपयोगकर्ता द्वारा परिभाषित तरीके से परिभाषित किया गया है, तो उसे प्राथमिकता दी जाएगी।

+3

प्रश्न के लेखक ने इसे स्पष्ट रूप से नहीं लिखा, लेकिन मुझे लगता है कि संदर्भित प्रश्नों के आधार पर, वह चाहता है कि प्रतिबिंब बराबर हो, जो ऑब्जेक्ट की तुलना कर रहा है, उन पर 'बराबर' विधि लागू किए बिना। 'ऑब्जेक्ट्स डीपइक्वाल्स (ऑब्जेक्ट ए, ऑब्जेक्ट बी)' प्रतिबिंब का उपयोग करके तुलना नहीं करता है। यह 'बराबर' विधि पर निर्भर करता है और 'गहरा' भाग संदर्भ प्रकार वाले फ़ील्ड नहीं, सरणी की तुलना करने के लिए संदर्भित करता है। – krzychu

0

मुझे नहीं लगता कि अपाचे EqualsBuilder एक भयानक उत्तर है, लेकिन एक साधारण इंटरफ़ेस के लिए जो आप चाहते हैं, आपको कॉल को थोड़ा सा लपेटना होगा। यहां एक उदाहरण दिया गया है।

public static <T> boolean matches(T actual, T expected, String... excludedFields) { 
    assert actual != null; 
    assert expected != null; 
    boolean matches = EqualsBuilder.reflectionEquals(actual, expected, 
      false /* testTransients */, 
      null /* reflectUpToClass */, 
      true /* testRecursive */, 
      excludedFields); 
    if (!matches) { 
     log.warn("Actual result doesn't match."); 
     logComparison(actual, expected); 
    } 
    return matches; 
} 

public static <T> void logComparison(T actual, T expected) { 
    //Making sure hashcodes don't thrown an exception 
    assert actual.hashCode() > Integer.MIN_VALUE; 
    assert expected.hashCode() > Integer.MIN_VALUE; 
    log.warn("Expected: \n" + reflectionToString(expected)); 
    log.warn("Actual: \n" + reflectionToString(actual)); 
} 
संबंधित मुद्दे