2011-12-09 16 views
9

क्या कोई तरीका टाइप एरर से बच सकता है और एक प्रकार पैरामीटर तक पहुंच प्राप्त कर सकता है?जावा टाइप एरर से बचें

public class Foo<T extends Enum<?> & Bar> { 
    public Foo() { 
     // access the template class here? 
     // i.e. : 
     baz(T.class); // obviously doesn't work 
    } 

    private void baz(Class<T> qux) { 
     // do stuff like 
     T[] constants = qux.getEnumConstants(); 
     ... 
    } 
} 

मुझे T के बारे में जानने की आवश्यकता है, और इसके साथ चीजें करें। क्या यह संभव है, और यदि हां, तो यह बिना के बिना कन्स्ट्रक्टर में या पैरामीटर के अलावा कहीं भी कक्षा में गुजर सकता है?

संपादित करें: इस सवाल का मुख्य उद्देश्य पता लगाने के लिए अगर वहाँ किसी भी व्यावहारिक तरीका आसपास प्रकार विलोपन है।

उत्तर

5

AFACT, आसपास प्रकार विलोपन नहीं व्यावहारिक तरीका है क्योंकि आप जो कुछ क्रम के लिए उपयोग नहीं है के लिए नहीं पूछ सकते है। निश्चित रूप से आप मानते हैं कि Bar इंटरफ़ेस लागू करने वाले प्रत्येक enum के लिए उप-वर्गीकरण जेनेरिक कक्षाएं व्यावहारिक कार्य है।

enum Test implements Bar { 
    ONE, TWO 
} 

class Foo<T> extends FooAbstract<Test> { 
    public Foo() { 
     ParameterizedType genericSuperclass = 
       (ParameterizedType) getClass().getGenericSuperclass(); 
     baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]); 
    } 

    private void baz(Class<T> qux) { 
     T[] constants = qux.getEnumConstants(); 
     System.out.println(Arrays.toString(constants)); // print [ONE, TWO] 
    } 
} 

interface Bar { 
} 

class FooAbstract<T extends Enum<?> & Bar> { 
} 
+2

+1 हाँ - यह एक और प्रतिबिंब-आधारित विकल्प है यदि आप 'कक्षा' ऑब्जेक्ट को पार करने के लिए उप-वर्गीकरण पसंद करते हैं। –

2

आप तैयार/निर्माता करने के लिए एक वर्ग टोकन सौंपने के लिए सक्षम हैं, तो:

public Foo(Class<T> clazz) { 
    baz(clazz); 
} 

private void baz(Class<T> qux) { 
    // ... 
} 

इस तरह, आप Class.newInstance(), करने के लिए मनमाने ढंग से वस्तुओं कास्ट करने के लिए प्रयास के साथ प्रकार टी की वस्तुओं का उत्पादन कर सकते कक्षा.कास्ट(), आदि का उपयोग टी

आप baz() में क्या करना चाहते हैं?

+0

मान लें कि यह दिए गए वर्ग को मूल्यों की सूची के लिए पूछता है और उन मानों का उपयोग करता है। कक्षा में गुजरना वह नहीं है जो मैं करना चाहता हूं। –

1

जैसे ही फोल्सर अपने उत्तर में बताता है, इसे प्राप्त करने का एकमात्र तरीका Class ऑब्जेक्ट T प्रकार का प्रतिनिधित्व करने वाला है। यह Type Erasure की वजह से है कि T.class जैसे कुछ संभव नहीं है क्योंकि T रनटाइम से पहले मिटा दिया गया है।

आप Class ऑब्जेक्ट में गुजरने के खिलाफ प्रतिरोधी प्रतीत होते हैं, लेकिन यह विधि getEnumConstants() विधि का उपयोग करने का एकमात्र तरीका है। यहाँ एक आत्म निहित उदाहरण है:

public class Foo<T extends Enum<?> & Bar> { 

    final Class<T> clazz; 

    public Foo(Class<T> clazz) { 

     this.clazz = clazz; 
    } 

    public void baz() { 

     T[] constants = clazz.getEnumConstants(); 

     System.out.println(Arrays.toString(constants)); 
    } 

    public static void main(String[] args) { 

     new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]" 
    } 
} 

public interface Bar { } 

public enum MyEnum implements Bar { A, B, C, D; } 
+2

तो मेरे पास टाइप एरर के आसपास जाने के लिए बिल्कुल कोई रास्ता नहीं है और 'टी' के रूप में पारित कक्षा को समझने का कोई तरीका नहीं है?इस धागे का विचार यह पता लगाना है कि टाइप एरर के आसपास कोई रास्ता है या नहीं। –

+1

@ क्रिस - प्रतिबिंब जावा में मिरर टाइप करने का एकमात्र कामकाज है। लेकिन आपको 'क्लास' ऑब्जेक्ट में गुज़रने से आपके पास जो कुछ भी है, उससे आपको कोई नुकसान नहीं होता है, हालांकि यह परेशान है और संकलन समय पर अनावश्यक दिखता है। ध्यान दें कि आप पहले से ही 'कक्षा # getEnumConstants() 'का उपयोग करके प्रतिबिंब पर भरोसा कर रहे हैं। एकमात्र विकल्प एक पूर्ण रीडिज़ाइन है जो उस विधि पर आपकी निर्भरता को हटा देता है। –

1

नील गफ्फर द्वारा प्रस्तावित एक सुपर प्रकार टोकन का उपयोग करें और इस उद्देश्य के लिए गुइसे जैसे पुस्तकालयों द्वारा उपयोग किया जाता है।

मूल विवरण के लिए http://gafter.blogspot.com/2006/12/super-type-tokens.html देखें और मैंने सीए रेडियो जीवन कार्य कार्यान्वयन के लिए गुइस स्रोत देखें।

एक और क्ष जो काम किया उदाहरण के साथ एक जवाब इनलाइन यहाँ How can I pass a Class as parameter and return a generic collection in Java?

0

कुछ मामलों आप एक समाधान के रिचर्ड गोम्स ने सुझाव दिया उपयोग कर सकते हैं में है नहीं है। अज्ञात वर्गों के उदाहरण बनाते समय, प्रकार पैरामीटर क्लास जानकारी उपलब्ध है।

class A<T> 
{ 
    A() 
    { 
     java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType) (this.getClass().getGenericSuperclass()); 
     System.out.println(parameterizedType.getActualTypeArguments()[0]); 
    } 
} 

public class Example { 
public static void main(String[] args) { 
    A<String> anonymous = new A<String>() {}; // prints java.lang.String 
} 
} 

ध्यान दें कि इस तरह से बनाई गई कई उदाहरण अलग गुमनाम वर्गों में से हो जाएगा, और आप नए के लिए कॉल को बदलने के लिए एक createNew() क्लोन के आधार पर समारोह के साथ एक कक्षा A_String_Factory चाहते हो सकता है कि अगर कोई समस्या है।

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