2015-01-02 9 views
7

मैं हाल ही में जावा जेनिक्स सीख रहा हूं, और बस "जावा जेनरिक एफएक्यू" हालांकि जाने की कोशिश कर रहा हूं।जावा जेनरिक वाइल्डकार्ड भ्रम

वाइल्डकार्ड पैरामीटरयुक्त प्रकार के बारे में प्रश्न (# 304) नीचे मुझे उलझन में, आपकी मदद की सराहना करेंगे।

कोड उदाहरण:

boolean equal = box.equalTo(box); 
equal = box.equalTo(new Box<String>("abc")); 

धन्यवाद

+4

त्रुटि क्या कहती है और आप इसके बारे में क्या समझ नहीं सकते? –

+0

@SotiriosDelimanolis ने सोचा कि बराबर के लिए पैरामीटर बॉक्स (0) बॉक्स होगा, और यह समझ में नहीं आता कि क्यों बॉक्स "बॉक्स" और "नया बॉक्स (" abc ")" तर्क के रूप में स्वीकार नहीं कर सकता है। – foolhunger

+0

जब आप त्रुटि कहते हैं, तो क्या आपका मतलब कंपाइलर त्रुटि या रनटाइम त्रुटि है? – smac89

उत्तर

7
Box<?> box = new Box<String>("abc"); 
box.put("xyz");  // error 
String s = box.take(); // error 
  1. OOP में, आप बहुरूपता उपयोग कर रहे हैं। समय संकलन में तो, बॉक्स वस्तु के प्रकार Box<?>

  2. Type<?> यह अज्ञात वाइल्डकार्ड कहा जाता है। क्योंकि आप नहीं जानते कि किस प्रकार का बॉक्स टाइप किया गया है, आप केवल उस ऑब्जेक्ट से पढ़ सकते हैं, और आप ऑब्जेक्ट इंस्टेंस के रूप में केवल ऑब्जेक्ट्स का उपयोग कर सकते हैं। यही कारण है कि box.put("xyz") त्रुटि प्राप्त हुई है और String s = box.take() त्रुटि प्राप्त हुई है।

दूसरी बात:

boolean equal = box.equalTo(box); 

equalToBox<T> नहीं Box<?> प्राप्त होता है। जैसा कि मैंने ऊपर बताया है, टी किसी भी वर्ग के लिए खड़ा है, लेकिन ? सिर्फ अज्ञात वाइल्डकार्ड का अर्थ है, वे दो शब्द समान नहीं हैं।

और अन्य बिंदु आपको पता होना चाहिए। जावा में, जेनेरिक संकलन-समय पर है। सी # जैसे अन्य के विपरीत, जेनेरिक रन-टाइम पर है।Java wildcard

आशा इस मदद :)

5

equalTo विधि एक Box<T>, नहीं Box<?> लेता है:

class Box<T> { 
    private T t; 
    public Box(T t) { this.t = t; } 
    public void put(T t) { this.t = t;} 
    public T take() { return t; } 
    public boolean equalTo(Box<T> other) { return this.t.equals(other.t); } 
    public Box<T> copy() { return new Box<T>(t); } 
} 

class Test { 
    public static void main(String[] args) { 
    Box<?> box = new Box<String>("abc"); 
    box.put("xyz");  // error 
    box.put(null);  // ok 

    String s = box.take(); // error 
    Object o = box.take(); // ok 

    boolean equal = box.equalTo(box); // error {confused} 
    equal = box.equalTo(new Box<String>("abc")); // error {confused} 

    Box<?> box1 = box.copy(); // ok 
    Box<String> box2 = box.copy(); // error 
    } 
} 

दो क्यों नीचे दी गई विधि असफल हो जायेगी कहा जाता है यह पता लगाने नहीं कर सकते। जब आपके पास Box<?> टाइप करने का ऑब्जेक्ट होता है, तो आप पर पैरामीटर के रूप में Box<String> या Box<?> को पैरामीटर के रूप में T दो बॉक्सों के प्रकार के समान नहीं रख सकते हैं।

याद रखें कि संकलक संकलन समय पर ऑब्जेक्ट के स्थिर प्रकार का उपयोग करेगा।

तो, यह विफल हो जाएगा:

Box<?> b = new Box<String>(); 
b.equalTo(new Box<String>("abc"); 

लेकिन यह ऐसा नहीं करेंगे:

Box<String> b = new Box<String>(); 
b.equalTo(new Box<String>("abc"); 
3

बाहर क्यों दो विधि

असफल हो जायेगी वे असफल क्योंकि यह है कहा जाता है नीचे आंकड़ा नहीं कर सकता:

यहाँ वाइल्डकार्ड के बारे में संदर्भ कड़ी है वाइल्डकार्ड कैसे काम करता है।

वाइल्डकार्ड "कुछ प्रकार का प्रतिनिधित्व करता है जिसे हम अब और नहीं जानते"।

चलिए एक सरल वर्ग बनाते हैं।

class Holder<T> { 
    private T obj; 

    void set(T obj) { 
     this.obj = obj; 
    } 

    T get() { 
     return obj; 
    } 
} 

जब हम एक Holder<?> है, हम हम इसे कैसे उपयोग कर सकते हैं के लिए विशेष नियम है। विशेष रूप से, हम एक सामान्य तर्क के साथ विधियों को कॉल नहीं कर सकते हैं। ऐसा इसलिए है क्योंकि हम नहीं जानते कि अब और किस प्रकार का है: ऐसा करना असुरक्षित होगा।

जब हम एक Holder<?> हम जैसे (धारणात्मक) कुछ है है:

class Holder<?> { 
    private X obj; 

    void set(X obj) { 
     this.obj = obj; 
    } 

    Object get() { 
     return obj; 
    } 
} 

कहाँ X प्रकार का मतलब हमारे लिए सीमा बंद है, क्योंकि हम नहीं जानते कि क्या इसे अब और है।

  • get रिटर्न Object क्योंकि है कि केवल वर्ग हम सुनिश्चित obj है हो सकता है
  • set सभी

मुझे लगता है यह अजीब लग सकता है क्योंकि अगर आपकी equalTo मूल रूप से की तरह घोषित किया गया था पर नहीं कहा जा सकता

public boolean equalTo(Box<?> other); 

तो आप इसे कॉल करने में सक्षम होंगे। हालांकि, वाइल्डकार्ड को ? के साथ बस प्रतिस्थापित करके काम नहीं करता है।

4
  • Box<?> "अज्ञात का एक बॉक्स" है।
  • Box<? extends String> "चीजें हैं जो कम से कम तार पर हैं की एक बॉक्स"
  • Box<String>निश्चित रूप से है "तार के एक बॉक्स" होगा।
  • तो यदि हमारे पास "अज्ञात बॉक्स" है, और हम इसमें एक प्रकार (एक स्ट्रिंग कहें) डालने का प्रयास करते हैं। कंपाइलर निश्चित नहीं है। यह अज्ञात का एक बॉक्स है। क्या होगा यदि यह वास्तव में केवल इंटीजर स्वीकार कर लिया जाए?
  • क्या हम null को "अज्ञात बॉक्स" में डाल सकते हैं? ज़रूर।
  • हम "अज्ञात बॉक्स" से "प्राप्त()" क्या करते हैं? कम से कम एक वस्तु।

यह देखते हुए कि,

Box<?> box = new Box<String>("abc"); 

इसके संकलक के लिए पूछ <String> के बारे में भूल जाते हैं और मान box "अज्ञात के एक बॉक्स" है।आप जो त्रुटियां देखते हैं, इंगित करते हैं कि कंपाइलर अब तर्कों की जांच प्रकार नहीं कर सकता है। यह जांच नहीं कर सकता कि दिया गया प्रकार अज्ञात या नहीं (शून्य के अलावा) से संबंधित है।

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