टाइप पैरामीटर के तात्कालिक वस्तु


89

मुझे निम्नानुसार एक टेम्पलेट वर्ग मिला है:

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

मैं अपनी कक्षा में टी का एक नया उदाहरण कैसे बनाऊं?

जवाबों:


86

प्रकार के क्षरण के बाद, सभी के बारे 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();
  }

}

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

@ user927387java.util.function.Supplier
erickson

आपूर्तिकर्ता <T> के लिए Java 8, JFTR की आवश्यकता होती है जहाँ भी इसकी कीमत है।
13

14

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

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

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

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

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


12

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

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

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

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

1
अच्छी कॉल - आप myMethod () में बनाई जाने वाली T की वस्तुओं और T के उपवर्गों की अनुमति देने के लिए फैक्ट्री में एक बाउंडेड वाइल्डकार्ड रखना चाहते हैं।
डैन हॉज


-3

कक्षा ClassOfT

        try {
            t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
        } catch (Exception e) {
            e.printStackTrace();
        }

2
वह क्लासऑफटी कक्षा कहाँ घोषित की गई है?
फ्रैंक मरोज़ा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.