2009-08-10 13 views
5

मैं जावा जेनरिक को समझने में समस्या आ रही है और मैं इस उदाहरणजावा परिपत्र जेनेरिक्स

class A<T extends B> { 

    public void fun(T t) { 

    } 
} 

class B { 
    A a; 

    public void event() { 
     a.fun(this); 
    } 

} 
को सरल बना दिया है

समस्या यह है कि यह एक चेतावनी है क्योंकि एक बी के अंदर परिभाषित किया गया है, लेकिन एक पहले से ही उपयोग कर रहा है उत्पन्न करता है एक सामान्य प्रकार के रूप में।

मेरा पहला वृत्ति यह होगा कि मेरा डिज़ाइन गलत है, लेकिन इस मामले में मैं इसे बदल नहीं सकता। ए संग्रह की तरह है और बी संग्रह में नोड की तरह है जिसे उपयोगकर्ताओं को ओवरराइड करना है। कुछ घटनाओं बी कि वापस जनक ए

के लिए रिपोर्टिंग की आवश्यकता होती है में हो सकता है लेकिन एक के बाद बी के साथ सामान्य रूप से परिभाषित किया गया है, मैं कैसे B.event() के अंदर संकलन चेतावनी से बचने करते

धन्यवाद

+0

एकमात्र चेतावनी जिसे मैं देख सकता हूं वह कच्चे प्रकार के रूप में उपयोग है। यदि वह चेतावनी नहीं है जिसका आप उल्लेख कर रहे हैं, तो कृपया अधिक विशिष्ट रहें, और हमें बताएं कि आप किस कंपाइलर का उपयोग कर रहे हैं। – skaffman

उत्तर

11

कोड

public class A<T extends B> { 
    public void fun(T t) { 
    } 
} 

public class B { 
    A<B> a; 

    public void event() { 
     a.fun(this); 
    } 
} 

चेतावनी परास्त कर रहा है।

कारण

प्रकार A के चर के रूप में सामान्य वर्ग हस्ताक्षर (A<T extends B>) ने सुझाव दिया, एक विशिष्ट वर्ग प्रकार का उपयोग घोषित किया जाना चाहिए।

संकल्प

इस संकलक चेतावनी को हल करता है, मूल समस्या बनी हुई है। लॉरेंस कोर मुद्दे के लिए एक उत्कृष्ट स्पष्टीकरण और समाधान प्रदान करता है।

13

A a; 

आप एक के प्रकार पैरामीटर (टी) का प्रकार निर्दिष्ट करने की जरूरत है: समस्या यह है कि आप इस लाइन पर एक कच्चे प्रकार का उपयोग कर रहे है।

आप कुछ इस तरह कर सकता है:

A<B> a; 

लेकिन फिर एक के रूप में अच्छी तरह से नहीं सामान्य बिल्कुल, हो सकता है अगर मैं समस्या के अपने विवरण को समझना रहा हूँ।

class A<T> { 
    public void fun(T t) { 

    } 
} 

class B<T extends B<T>> { 
    A<B<T>> a; 
    public void event() { 
    a.fun(this); 
    } 
}  

या यहाँ तक कि इस: आप शायद इस तरह कुछ करना चाहता हूँ

class A<T extends B<? extends T>> { 
    public void fun(T t) { 

    } 
} 

class B<T extends B<T>> { 
    A<? super B<T>> a; 
    public void event() { 
    a.fun(this); 
    } 
} 

के बीच बदलाव के इन कि संभवतः रूप में अच्छी तरह से उपयोगी होते हैं के एक जोड़े हैं। उत्तरार्द्ध उदाहरण सबसे सामान्य है (लेकिन जाहिर है, यह भी सबसे जटिल)।

class A<T extends B<? extends T>> यह सुनिश्चित कर रहा है कि ए के लिए प्रकार पैरामीटर बी है। बी बी स्वयं ही सामान्य है, और उस चक्रीय प्रकार पैरामीटर है, तो आपको B<? extends T> कहने की आवश्यकता है (बस यह कहकर टी यहां काम नहीं करेगा)।

class B<T extends B<T>> उतना ही करीब है जितना आप जावा में "स्वयं प्रकार" को अनुकरण करने के लिए प्राप्त कर सकते हैं। यह बी को अपने बारे में (लगभग) ठोस उपप्रकार के बारे में बात करने देता है। जब बी को उपclassing आप कुछ कहेंगे "class C extends <B<C>>"। यह उपयोगी है क्योंकि अब C.a का प्रकार वास्तव में A<? super B<C>> है।

बाद के उदाहरण में ? super बिट केवल उपयोगी है यदि आप A के साथ बी को कनेक्ट करने की योजना बनाते हैं जो ठीक उसी प्रकार के B के लिए नहीं है। ठोस शब्दों में सोचते हुए, मान लीजिए कि आपके पास A<Shape> और Circle था (जो Shape बढ़ाता है जो B बढ़ाता है)। सुपर वाइल्डकार्ड आपको एक साथ उनका उपयोग करने देता है। इसके बिना आपको Circle के लिए A<Shape> की बजाय A<Circle> की आवश्यकता होगी।

+0

यह सही है, और वाइल्डकार्ड का एक बड़ा उदाहरण है। –

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