मुझे निम्नानुसार एक टेम्पलेट वर्ग मिला है:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
मैं अपनी कक्षा में टी का एक नया उदाहरण कैसे बनाऊं?
मुझे निम्नानुसार एक टेम्पलेट वर्ग मिला है:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
मैं अपनी कक्षा में टी का एक नया उदाहरण कैसे बनाऊं?
जवाबों:
प्रकार के क्षरण के बाद, सभी के बारे 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();
}
}
java.util.function.Supplier
एक अन्य गैर-चिंतनशील दृष्टिकोण हाइब्रिड बिल्डर / एब्सट्रैक्ट फैक्ट्री पैटर्न का उपयोग करना है।
प्रभावी जावा में, यहोशू बलोच बिल्डर पैटर्न पर विस्तार से जाता है, और एक सामान्य बिल्डर इंटरफ़ेस की वकालत करता है:
public interface Builder<T> {
public T build();
}
कंक्रीट बिल्डर्स इस इंटरफ़ेस को लागू कर सकते हैं, और बाहरी वर्ग बिल्डर को कॉन्फ़िगर करने के लिए कंक्रीट बिल्डर का उपयोग कर सकते हैं। बिल्डर को MyClass को एक के रूप में पारित किया जा सकता है Builder<T>
।
इस पैटर्न का उपयोग करके, आप नए इंस्टेंसेस प्राप्त कर सकते हैं T
, भले ही T
कंस्ट्रक्टर पैरामीटर हों या अतिरिक्त कॉन्फ़िगरेशन की आवश्यकता हो। बेशक, आपको MyClass में बिल्डर को पास करने के लिए किसी तरह की आवश्यकता होगी। यदि आप MyClass में कुछ भी पास नहीं कर सकते हैं, तो बिल्डर और एब्सट्रैक्ट फ़ैक्टरी बाहर हैं।
यह आपके द्वारा खोजे जाने की तुलना में अधिक भारी हो सकता है, लेकिन यह भी काम करेगा। ध्यान दें कि यदि आप इस दृष्टिकोण को लेते हैं, तो फैक्ट्री को MyClass में इंजेक्ट करने के लिए और अधिक समझ में आता है जब इसे हर बार इसे अपने तरीके से पारित करने के बजाय इसका निर्माण किया जाता है।
interface MyFactory<T>
{
T newObject();
}
class MyClass<T>
{
T field;
public void myMethod(MyFactory<T> factory)
{
field = factory.newObject()
}
}
यदि आप उपवर्ग के लिए तैयार हैं तो आप इरिटेशन से भी बच सकते हैं, http://www.artima.com/weblogs/viewpost.jsp?thread=208860 देखें
कक्षा ClassOfT
try {
t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
} catch (Exception e) {
e.printStackTrace();
}
Supplier
स्थित है? `MyClass (क्लास <; फैली हुई टी> निहित)` को घोषित करना चाहिए 'NoSuchMethodException' फेंकता है। आपका उत्तर दुर्भाग्य से जावा शुरुआती के अनुकूल नहीं है।