2015-02-11 9 views
6

Spring MVC पर अवधारणाओं को समझने की कोशिश करने के बाद, मैं Collection<? extends Book> अभिव्यक्ति में आया जो मैंने पहले कभी नहीं देखा है। मैंने इसे अपने आप समझने की कोशिश की है, लेकिन मुझे Collection<? extends Book> और Collection<Book> का उपयोग करने के बीच कोई अंतर नहीं दिख रहा है। मैं अनुमान लगा रहा था कि इसे केवल पुस्तक के विस्तार की अनुमति है, लेकिन यह पुस्तक के लिए भी अनुमति देता है। तो उस खरोंच। मैंने Google का उपयोग करने का प्रयास किया है, लेकिन तब से? गूगल में वाइल्डकार्ड है, यह खोजना लगभग असंभव बनाता है। मैंने जवाब के लिए स्टैक ओवरफ्लो खोजा है, लेकिन इसके बारे में सभी प्रश्न (जैसे List<? extends MyType> और <? extends > Java syntax) पहले से ही Collection<? extends T> का ज्ञान मानते हैं।संग्रह <? extends T> बनाम संग्रह <T>

import java.util.ArrayList; 
import java.util.Collection; 

public class Book { 
    public static void main(String[] args) { 
     BookCase bookCase1 = new BookCase(); 
     BookCase bookCase2 = new BookCase(bookCase1); 
    } 
} 

class BookCase extends ArrayList<Book> { 
    public BookCase() { 
    } 

    //acts same as public BookCase(Collection<Book> c) { 
    public BookCase(Collection<? extends Book> c) { 
     super(c); 
    } 
} 

<? extends T> क्या करता है: यहाँ कोड है कि शुरू में मेरी रुचि intrigued गया है? <T> से यह अलग कैसे है?

संपादित करें:

फॉलोअप प्रश्न: BookCase extends ArrayList<Book> मतलब यह है कि BookCase फैली Book?

public class Test { 
    public static void main(String[] args) { 
     BookCase bookCase1 = new BookCase(); 
     BookCase bookCase2 = new BookCase(bookCase1); 
     List<FictionBook> fictionBooks = new ArrayList<>(); 
     BookCase bookCase3 = new BookCase(fictionBooks); 
    } 
} 

class Book {} 
class FictionBook extends Book {} 

class BookCase extends ArrayList<Book> { 
    public BookCase() { 
    } 

    //does not act same as public BookCase(Collection<Book> c) { 
    public BookCase(Collection<? extends Book> c) { 
     super(c); 
    } 
} 

कि कोड को संकलित करता है:

+2

एक 'संग्रह ' एक संग्रह है 'लेकिन संग्रह नहीं 'संग्रह ' बढ़ाता है। – immibis

+0

इस तरह के टाइम्स मेरी इच्छा है कि मैं कई उत्तरों को हरा चेकमार्क कर सकता हूं। विशेष रूप से मकोटो और एडम के जवाब। हालांकि सभी उत्तर उपयोगी थे, विशेष रूप से उन लोगों ने मुझे इसे समझने में मदद की। तो यदि आप इस प्रश्न का उत्तर ढूंढ रहे हैं, तो मेरा सुझाव है कि आप उन दोनों को कम से कम टिप्पणियों सहित पढ़ें। सबको धन्यवाद!! – Evorlor

उत्तर

3

निम्नलिखित

class Animal { } 
class Horse extends Animal { } 

private static void specific(List<Animal> param) { } 
private static void wildcard(List<? extends Animal> param) { } 

पर विचार करें आप केवल हस्ताक्षर

specific(new ArrayList<Horse>()); // <== compiler error 

वाइल्डकार्ड के साथ में सही वर्ग का उपयोग कर सकते फैली आप पशु के किसी भी उपवर्गों अनुमति दे सकते हैं

wildcard(new ArrayList<Horse>()); // <== OK 

आमतौर पर इसका उपयोग करना बेहतर होता है? वाक्यविन्यास बढ़ाता है क्योंकि यह आपके कोड को अधिक पुन: प्रयोज्य और भविष्य के सबूत बनाता है।

+1

लेकिन एक घोड़ा एक जानवर है, और विशिष्ट() जानवरों की एक सूची स्वीकार करता है ... तो घोड़ों की एक सूची क्यों स्वीकार नहीं की जाएगी? – Evorlor

+0

जेनरिक मानक विधि हस्ताक्षर के समान काम नहीं करता है, हाँ foo (पशु पशु) किसी भी प्रकार का पशु ले सकता है। – Adam

+1

@Evorlor क्योंकि यदि आप कुछ ऑब्जेक्ट होने के लिए टाइप पैरामीटर निर्दिष्ट करते हैं, तो संकलक चाहता है कि यह सटीक ऑब्जेक्ट –

2

यहाँ उदाहरण है कि स्पष्ट रूप से Collection<? extends Book> और Collection<Book> के बीच अंतर पता चलता है। यदि आप के कन्स्ट्रक्टर पैरामीटर को Collection<Book> पर बदलते हैं, तो यह उदाहरण संकलित नहीं होगा।

4

दस्तावेज से this देखें।

सामान्य में, अगर फू बार की एक उप-प्रकार (उपवर्ग या subinterface) है, और जी कुछ सामान्य प्रकार घोषणा है, यह मामला है कि जी जी की एक उप-प्रकार है यह शायद सबसे मुश्किल बात यह है कि आप नहीं है जेनेरिक के बारे में जानने की जरूरत है, क्योंकि यह हमारे गहन अंतर्निहित अंतर्ज्ञानों के खिलाफ है।

next page about wildcards पर भी एक नज़र डालें।

तो मूल रूप से जब आप void doStuff(List<Book>){} लिखते हैं तो आप केवल Book ऑब्जेक्ट्स की सूची में सामान ही कर सकते हैं।

नहींNovel रों, नहींMagazine रों, नहींComicBook रों।

फिर, यह क्योंकि यद्यपि Novel फैली Book, G<Novel>वास्तव मेंG<Book> विस्तार नहीं करता है। यह बहुत सहज नहीं है, लेकिन दस्तावेज़ीकरण में उदाहरण आपको इसे देखने में मदद करेगा।बिना वाक्य रचना फैली

3

दोनों Collection<Book> और Collection<? extends Book> एक संग्रह है कि Book उदाहरणों और वस्तुओं है कि एक Book के माध्यम से है-एक संबंध होने के लिए विचार किया जा सकता कर सकते हैं प्रतिनिधित्व करता है। यह संपत्ति इंटरफ़ेस तक भी फैली हुई है।

यहां अंतर यह है कि बाद का फॉर्म माना जाता है। बाध्य के आधार पर, आप इस संग्रह से तत्वों को जोड़ने या हटाने में सक्षम नहीं होंगे।

? extends Tupper bounded wildcard है। असल में, यह कम अंत में कुछ प्रकार (?) और उच्च अंत में Book के बीच एक पदानुक्रमित बाध्य का वर्णन करता है। यह समावेशी है, तो आप वहाँ में Book के उदाहरण स्टोर कर सकते हैं, लेकिन आप इस तरह के रूप में अन्य वर्गों और इंटरफेस, था:

class Novella extends Book {} 
class Magazine extends Book {} 
class ComicBook extends Book{} 
class Manga extends Magazine {} 
class Dictionary extends Book {} 
class ForeignLanguageDictionary<T extends Language> extends Dictionary {} 
interface Language {} 

... आप एक Collection<? extends Book> के अंदर ऐसे मामलों में से किसी पा सके।

याद रखें कि मैंने उल्लेख किया है कि आप इस संग्रह से चीजों को जोड़ने या हटाने में सक्षम नहीं हो सकते हैं? इस सम्मेलन को याद रखें:

निर्माता विस्तारित करता है; उपभोक्ता सुपर

ध्यान दें कि यह संग्रह के परिप्रेक्ष्य से है; अगर संग्रह extends से घिरा हुआ है, तो यह एक निर्माता है; अगर यह super से घिरा हुआ है, तो यह उपभोक्ता है।

यह कहा गया कि, इस संग्रह के परिप्रेक्ष्य से, यह पहले से ही अपने सभी रिकॉर्ड तैयार कर चुका है, इसलिए आप इसमें नए नहीं जोड़ सकते हैं।

List<? extends Book> books = new ArrayList<>(); // permanently empty 
books.add(new Book()); // illegal 

यदि यह मामला है कि आप था यह ? super Book साथ बंधे हुए थे, तो आप एक समझदार तरीके से से तत्वों प्राप्त नहीं कर सके - आप जो संक्षिप्त नहीं है बजाय Object के रूप में उन्हें पुन: प्राप्त करने, होगा।

List<? super Book> books = new ArrayList<>(); 
books.add(new Book()); 
books.add(new Manga()); 
Book book = books.get(0); // can't guarantee what Book I get back 

मुख्यतः, यदि आप ? super T साथ बंधे हुए हैं, आप केवल कभी डालने के लिए है कि संग्रह में तत्वों इरादा रखते हैं।

फ़ॉलोअर्स प्रश्न: BookCase extends ArrayList<Book> का मतलब है कि BookCase extends Book?

नं कि उदाहरण में एक BookCase एक ArrayList, नहीं एक Book है। ऐसा लगता है कि सरणी सूची पुस्तकों को स्टोर करने के लिए बाध्य है, लेकिन यह Book नहीं है।

+0

तो टी के माध्यम से निम्नतम बच्चे का प्रतिनिधित्व करता है, जबकि का अर्थ है टी और केवल टी - कोई बच्चा नहीं। क्या ये सही है? – Evorlor

+0

यह वही है-बच्चों के साथ संबंध है, इसलिए आप बच्चों को 'टी' के अंदर स्टोर करने में सक्षम होंगे। मेरे उदाहरण में, आप 'संग्रह ' के अंदर 'मंगा' का उदाहरण डाल सकते हैं। – Makoto

+0

मुझे यहां कुछ बदलाव करने दें। जगह में थोड़ा उलझन है। – Makoto

0

List<Book> एक सूची है जिसमें कोई पुस्तक हो सकती है। क्योंकि इस तरह की पुस्तक पर कोई प्रतिबंध नहीं है, आप इसमें कोई भी पुस्तक जोड़ सकते हैं।

List<? extends Book> अच्छी तरह से एक सूची है जिसमें किताबें हैं, लेकिन वहां और प्रतिबंध भी हो सकते हैं। शायद वास्तव में यह List<PoetryBook> है और यह केवल PoetryBook के उदाहरणों को संग्रहीत कर सकता है, आप केवल यह सुनिश्चित कर सकते हैं कि इस सूची के अंदर प्रत्येक आइटम एक पुस्तक है। इस संभावित प्रतिबंध के कारण आप इस सूची में कोई भी आइटम नहीं जोड़ सकते हैं।

ऐसी किसी विधि पर विचार करें जो पुस्तकों की एक सूची लेता है और अधिकांश पृष्ठों के साथ पुस्तक लौटाता है।

Book getBookWithMostPages(List<? extends Book>) { 
    ... 
} 

इस विधि List<Book> साथ या List<PoetryBook> साथ कहा जा सकता है।

आप

Book getBookWithMostPages(Iterable<? extends Book>) { 
    ... 
} 

तो यह भी Set<ScienceBook> या कुछ भी है कि iterable है और किताबें शामिल हैं के साथ इस्तेमाल किया जा सकता करने के लिए हस्ताक्षर को बदलते हैं।

+0

... लेकिन एक विधि जो किताबों की सूची में कुछ कविता जोड़ती है: 'addSomePoetry (सूची )' काम नहीं करेगी। (बस अपनी व्याख्या को बंद कर दें।) –

+0

हां, यही बात है। – phlogratos

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