2008-11-18 17 views
64

की वस्तु instantiating मैं एक टेम्पलेट वर्ग इस प्रकार मिल गया है:प्रकार पैरामीटर

class MyClass<T> 
{ 
    T field; 
    public void myMethod() 
    { 
     field = new T(); // gives compiler error 
    } 
} 

मैं अपने वर्ग में टी का एक नया उदाहरण बना सकता हूँ?

उत्तर

57

टाइप एरर के बाद, T के बारे में ज्ञात सभी यह है कि यह Object का कुछ उप-वर्ग है। T के उदाहरण बनाने के लिए आपको कुछ फैक्ट्री निर्दिष्ट करने की आवश्यकता है।

एक दृष्टिकोण इस्तेमाल कर सकते हैं एक Supplier<T>:

class MyClass<T> { 

    private final Supplier<? extends T> ctor; 

    private T field; 

    MyClass(Supplier<? extends T> ctor) { 
    this.ctor = Objects.requireNonNull(ctor); 
    } 

    public void myMethod() { 
    field = ctor.get(); 
    } 

} 

प्रयोग इस प्रकार दिखाई देंगे:

MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new); 

वैकल्पिक रूप से, आप एक Class<T> वस्तु प्रदान कर सकते हैं, और फिर प्रतिबिंब का उपयोग करें।

class MyClass<T> { 

    private final Constructor<? extends T> ctor; 

    private T field; 

    MyClass(Class<? extends T> impl) throws NoSuchMethodException { 
    this.ctor = impl.getConstructor(); 
    } 

    public void myMethod() throws Exception { 
    field = ctor.newInstance(); 
    } 

} 
+0

क्या पैकेज 'Supplier' में स्थित है? 'माइक्लास (कक्षा इम्प्लायर) 'घोषित किया जाना चाहिए' संकलित करने के लिए NoSuchMethodException' फेंकता है। आपका उत्तर दुर्भाग्य से जावा शुरुआती के अनुकूल नहीं है। – user927387

+0

@ user927387 'java.util.function.Supplier' – erickson

10

की जाँच यह आपको क्या ढूंढ रहे हैं और अधिक से अधिक दिग्गज हो सकता है, लेकिन यह भी काम करेंगे। ध्यान दें कि यदि आप इस दृष्टिकोण को लेते हैं, तो यह कारखाने को माईक्लास में इंजेक्ट करने के लिए और अधिक समझ में आता है जब इसे हर बार इसे आपके तरीके में पारित करने के बजाय बनाया जाता है।

interface MyFactory<T> 
{ 
    T newObject(); 
} 

class MyClass<T> 
{ 
    T field; 
    public void myMethod(MyFactory<T> factory) 
    { 
     field = factory.newObject() 
    } 
} 
+1

अच्छा, गैर-परावर्तक दृष्टिकोण; प्रतिबिंब हमेशा एक विकल्प नहीं है। myMethod एक MyFactory स्वीकार करने में सक्षम होना चाहिए, है ना? – erickson

+0

अच्छी कॉल - आप कारखाने पर एक बाध्य वाइल्डकार्ड डालना चाहते हैं ताकि टी के प्रकार और टी के उप-वर्गों को myMethod() में बनाया जा सके। –

11

एक अन्य गैर-प्रतिबिंबित दृष्टिकोण एक संकर बिल्डर/सार फैक्टरी पैटर्न का उपयोग करना है।

प्रभावी जावा में, यहोशू बलोच विस्तार से बिल्डर पैटर्न के ऊपर जाता है, और एक सामान्य बिल्डर इंटरफ़ेस अधिवक्ताओं:

public interface Builder<T> { 
    public T build(); 
} 

कंक्रीट बिल्डरों इस इंटरफ़ेस को लागू कर सकते हैं और बाहर वर्गों कॉन्फ़िगर करने के लिए ठोस बिल्डर उपयोग कर सकते हैं आवश्यकतानुसार बिल्डर। बिल्डर को MyClass को Builder<T> के रूप में पास किया जा सकता है।

इस पैटर्न का उपयोग करके, आप T के नए उदाहरण प्राप्त कर सकते हैं, भले ही T में रचनात्मक पैरामीटर हैं या अतिरिक्त कॉन्फ़िगरेशन की आवश्यकता है। बेशक, बिल्डर को MyClass में पास करने के लिए आपको कुछ रास्ता चाहिए। यदि आप MyClass में कुछ भी पास नहीं कर सकते हैं, तो बिल्डर और सार फैक्टरी बाहर हैं।

1

कक्षा classOfT

 try { 
      t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
संबंधित मुद्दे