2008-12-12 3 views
11

मेरी प्रोजेक्ट पर FindBugs चलाते समय, मुझे ऊपर वर्णित त्रुटि के कुछ उदाहरण मिल गए।Findbugs चेतावनी: समान विधि को इसके तर्क के प्रकार के बारे में कुछ भी नहीं मानना ​​चाहिए

अर्थात्, बराबर के मेरे ओवरराइडिंग संस्करणों ने आरएचएस ऑब्जेक्ट को उसी प्रकार के रूप में डाला जिस पर ओवरराइडिंग संस्करण परिभाषित किया गया है।

हालांकि, मुझे यकीन नहीं है कि एक बेहतर डिज़ाइन संभव है, क्योंकि AFAIK जावा विधि पैरामीटर में भिन्नता की अनुमति नहीं देता है, इसलिए बराबर पैरामीटर के लिए किसी अन्य प्रकार को परिभाषित करना संभव नहीं है।

क्या मैं कुछ गलत कर रहा हूं, या FindBugs बहुत उत्सुक है?

इस सवाल का वाक्यांश करने का एक अलग तरीका यह है कि यदि वस्तु बराबर होती है तो सही व्यवहार क्या होता है, यह एलएचएस के समान नहीं होता है: क्या यह गलत है, या अपवाद होना चाहिए?

उदाहरण के लिए:

public boolean equals(Object rhs) 
{ 
    MyType rhsMyType = (MyType)rhs; // Should throw exception 
    if(this.field1().equals(rhsMyType.field1())... // Or whatever 
} 
+0

जो थोड़ा अजीब लगता है। कृपया हमें कुछ कोड दिखाएं। –

उत्तर

27

आमतौर पर, जब लागू करने के बराबर होती है तो आप इसे कास्टिंग से पहले लागू करने वर्ग के लिए है कि क्या तर्क के वर्ग बराबर (या संगत) है देखने के लिए जाँच कर सकते हैं। कुछ ऐसा:

if (getClass() != obj.getClass()) 
    return false; 
MyObj myObj = (MyObj) obj; 

ऐसा करने से यह FindBugs चेतावनी को रोक देगा।

एक टिप्पणी को संबोधित करने के लिए एक ओर ध्यान दें:
कुछ लोगों प्रकार सुरक्षा की जांच करने के instanceof बजाय getClass उपयोग करने के लिए लोगों का तर्क है। उस पर एक बड़ी बहस है, जिसे मैं अंदर आने की कोशिश नहीं कर रहा था जब मैंने देखा कि आप वर्ग समानता या संगतता की जांच कर सकते हैं, लेकिन मुझे लगता है कि मैं इससे बच नहीं सकता। यह इस तक उबाल जाता है - यदि आप instanceof का उपयोग करते हैं तो आप कक्षा के उदाहरणों और इसके उप-वर्ग के उदाहरणों के बीच समानता का समर्थन कर सकते हैं, लेकिन आप equals के सममित अनुबंध को तोड़ने का जोखिम उठा सकते हैं। आम तौर पर मैं instanceof का उपयोग न करने की अनुशंसा करता हूं जबतक कि आपको पता न हो कि आपको इसकी आवश्यकता है और आप जानते हैं कि आप क्या कर रहे हैं। अधिक जानकारी के लिए देखें:

+4

अनिवार्य रूप से इसका क्या अर्थ है: क्लासकास्ट अपवाद को फेंकने के बजाय, आपकी बराबर() विधि को झूठी वापसी करनी चाहिए। – Darron

+0

लेकिन क्या यह उन परिस्थितियों में सही अभ्यास है? मेरा मतलब है, आदर्श रूप में मुझे एक संकलन-समय प्रकार की जांच पसंद आएगी, जिसे मैं जावा सीमाओं के कारण प्राप्त नहीं कर सकता। – Uri

+0

क्यों? असंबद्ध प्रकारों के बीच समानता की जांच करने में क्या गलत है? यह एक बिल्कुल सही और अच्छी तरह से परिभाषित उत्तर के साथ एक सवाल है। –

7

आप शायद कुछ इस तरह कर रहे हैं:

public class Foo { 
    // some code 

    public void equals(Object o) { 
    Foo other = (Foo) o; 
    // the real equals code 
    } 
} 

इस उदाहरण आप बराबर() के तर्क के बारे में कुछ मानते हैं में: आप इसे प्रकार फू की है मानते हैं। यह मामला नहीं होना चाहिए! आप एक स्ट्रिंग भी प्राप्त कर सकते हैं (जिस स्थिति में आपको लगभग निश्चित रूप से झूठी वापसी करनी चाहिए)।

तो अपने कोड इस तरह दिखना चाहिए:

public void equals(Object o) { 
    if (!(o instanceof Foo)) { 
    return false; 
    } 
    Foo other = (Foo) o; 
    // the real equals code 
} 

(या अधिक कठोर getClass() != o.getClass() डेव एल ने उल्लेख का उपयोग

तुम भी इसे इस तरह से दे सकता है:

Integer i = new Integer(42); 
String s = "fourtytwo"; 
boolean b = i.equals(s); 

क्या कोई कारण है कि इस कोड को सामान्य रूप से खत्म करने के बजाय ClassCastException फेंकना चाहिए और b सेपर सेट करना चाहिए 10?

को .equals() के जवाब के रूप में फेंकना समझदार नहीं होगा। क्योंकि यहां तक ​​कि अगर यह एक बेवकूफ सवाल है ("बेशक एक स्ट्रिंग कभी भी फू के बराबर नहीं है!") यह अभी भी एक बिल्कुल सही जवाब है ("नहीं" == false)।

0

मैं इस तरह मेरी बराबरी (वस्तु) कार्यान्वयन शुरू:

if ((object == null) || !(object instaceof ThisClass)) { 
    return false; 
} 

यह भी FindBugs चेतावनी नहीं कर पाएगा लेकिन स्वचालित रूप से false नहीं लौटेगा जब ThisClass का एक उपवर्ग में सौंप दिया जा रहा है यह भी माना जा सकता है। बराबर, विशेष रूप से यदि इसकी equals(Object) विधि ओवरराइड नहीं की गई है।

+3

शून्य जांच उदाहरण के साथ अनावश्यक है। उदाहरण का उपयोग करके सावधान रहें; यदि गैर-फाइनल बराबर के परिष्कृत अनुबंध समानता के लिए शर्तों का वर्णन नहीं करते हैं (जैसे java.util.Set करता है), तो आप समरूपता आवश्यकता को तोड़ने की संभावना रखते हैं। – erickson

1

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

उदाहरण के लिए, यदि आपके पास 'ArrayList फ़ाइलें' हैं और फ़ाइलें.contains ("MyFile.txt") पर कॉल करें, तो आपको अच्छा होगा यदि आपको क्लासकास्ट अपवाद मिला। इसके बजाए, जावा सिर्फ झूठा लौटाता है, और जब तक आप उस बग को नहीं खोज लेते हैं, तो इसमें काफी समय लगता है।

संबंधित मुद्दे