java - जावा संग्रह क्यों सामान्य तरीकों को हटा नहीं रहे हैं?




api generics (6)

अन्य उत्तरों के अलावा, एक और कारण है कि विधि को Object को स्वीकार करना चाहिए, जो भविष्यवाणी करता है। निम्नलिखित नमूने पर विचार करें:

class Person {
    public String name;
    // override equals()
}
class Employee extends Person {
    public String company;
    // override equals()
}
class Developer extends Employee {
    public int yearsOfExperience;
    // override equals()
}

class Test {
    public static void main(String[] args) {
        Collection<? extends Person> people = new ArrayList<Employee>();
        // ...

        // to remove the first employee with a specific name:
        people.remove(new Person(someName1));

        // to remove the first developer that matches some criteria:
        people.remove(new Developer(someName2, someCompany, 10));

        // to remove the first employee who is either
        // a developer or an employee of someCompany:
        people.remove(new Object() {
            public boolean equals(Object employee) {
                return employee instanceof Developer
                    || ((Employee) employee).company.equals(someCompany);
        }});
    }
}

मुद्दा यह है कि remove विधि को पारित करने वाली वस्तु equals विधि को परिभाषित करने के लिए ज़िम्मेदार है। बिल्डिंग भविष्यवाणी इस तरह से बहुत आसान हो जाती है।

Collection.remove (ऑब्जेक्ट ओ) जेनेरिक क्यों नहीं है?

लगता है कि Collection<E> boolean remove(E o); हो सकता है boolean remove(E o);

फिर, जब आप गलती से निकालने का प्रयास करते हैं (उदाहरण के लिए) Collection<String> से प्रत्येक व्यक्ति स्ट्रिंग के बजाय Set<String> , तो बाद में डीबगिंग समस्या के बजाय यह एक संकलित समय त्रुटि होगी।


एक और कारण इंटरफेस की वजह से है। इसे दिखाने के लिए यहां एक उदाहरण दिया गया है:

public interface A {}

public interface B {}

public class MyClass implements A, B {}

public static void main(String[] args) {
   Collection<A> collection = new ArrayList<>();
   MyClass item = new MyClass();
   collection.add(item);  // works fine
   B b = item; // valid
   collection.remove(b); /* It works because the remove method accepts an Object. If it was generic, this would not work */
}

क्योंकि यह मौजूदा (प्री-जावा 5) कोड तोड़ देगा। जैसे,

Set stringSet = new HashSet();
// do some stuff...
Object o = "foobar";
stringSet.remove(o);

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


जोश ब्लोच और बिल पुग जावा पज़लर्स IV में इस मुद्दे का उल्लेख करते हैं : द फैंटम रेफरेंस मेनस, क्लोन का हमला, और शिफ्ट का बदला

जोश ब्लोच कहते हैं (6:41) कि उन्होंने मानचित्र की विधि, विधि को हटाने और कुछ अन्य को उत्पन्न करने का प्रयास किया, लेकिन "यह बस काम नहीं करता"।

ऐसे कई उचित प्रोग्राम हैं जिन्हें जनरेट नहीं किया जा सका यदि आप केवल सामान्य प्रकार के संग्रह को पैरामीटर प्रकार के रूप में अनुमति देते हैं। उनके द्वारा दिया गया उदाहरण संख्याओं की List और Long एस की List का एक चौराहे है।


मान लें कि किसी के पास Cat संग्रह है, और कुछ ऑब्जेक्ट संदर्भ Animal , Cat , SiameseCat और Dog संदर्भ हैं। संग्रह से पूछना कि क्या इसमें Cat या SiameseCat संदर्भ द्वारा संदर्भित वस्तु शामिल है, उचित लगता है। यह पूछने पर कि क्या Animal संदर्भ द्वारा संदर्भित वस्तु शामिल है, वह डोडी लग सकती है, लेकिन यह अभी भी पूरी तरह से उचित है। प्रश्न में वस्तु, आखिरकार, Cat हो सकती है, और संग्रह में दिखाई दे सकती है।

इसके अलावा, अगर वस्तु Cat अलावा कुछ और होती है, तो यह कहने में कोई समस्या नहीं है कि यह संग्रह में दिखाई देता है - बस जवाब दें "नहीं, यह नहीं है"। किसी प्रकार का "लुकअप-स्टाइल" संग्रह किसी भी सुपरटेप के संदर्भ को अर्थपूर्ण रूप से स्वीकार करने में सक्षम होना चाहिए और यह निर्धारित करना चाहिए कि ऑब्जेक्ट संग्रह के भीतर मौजूद है या नहीं। यदि पास-इन ऑब्जेक्ट संदर्भ एक असंबंधित प्रकार का है, तो संग्रह में संभवतः कोई तरीका नहीं हो सकता है, इसलिए क्वेरी कुछ अर्थपूर्ण नहीं है (यह हमेशा "नहीं" का उत्तर देगी)। फिर भी, चूंकि पैरामीटर को उपप्रकार या सुपरटाइप होने के लिए प्रतिबंधित करने का कोई तरीका नहीं है, इसलिए किसी भी ऑब्जेक्ट के लिए किसी भी प्रकार के उत्तर और उत्तर "नहीं" को स्वीकार करना सबसे व्यावहारिक है जिसका प्रकार संग्रह के साथ असंबंधित है।


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





collections