2011-06-01 31 views
8

परिणाम एक सामान्य प्रकार होने पर Class.forName() पर कैसे कॉल करूं? आम तौर पर मैं asSubclass() का उपयोग कर सकता हूं, लेकिन यहां एकमात्र तरीका है जिसे मैं ऐसा करने के लिए देखता हूं, एक कास्ट है, जो & बाहर निकलता है, जब सब कुछ जेनेरिक के साथ अच्छी तरह से टाइप किया जाता है।नाम वर्ग के लिए नाम वर्ग

एक प्रवेश बिंदु मुख्य वर्ग एक main() है कि के साथ एक .jar है:

परिदृश्य कुछ इस तरह चला जाता है। यह कक्षा नाम का विकल्प लेता है (और कुछ अन्य, यहां अप्रासंगिक)। दिया गया वर्ग Callable<Integer> लागू करता है। इस वर्ग को लोड किया गया है, & लॉन्च किया गया।

Class<? extends Callable<Integer>> clazz = (Class<? extends Callable<Integer>>) Class.forName(options.valueOf(className)).asSubclass(Callable.class); 

वहाँ किसी भी तरह से है कि कलाकारों से छुटकारा पाने के है:

यहाँ मैं क्या जरूरत का एक उदाहरण है?

एसई 6 का उपयोग करना।

उत्तर

10

सबसे पहले तो आप शायद हम classCI कैसे प्राप्त कर सकते हैं एक पूर्ण सामान्य Class

Class<Callable<Integer>> classCI = ...; 

फिर जावा प्रकार प्रणाली

Class<? extends Callable<Integer>> clazz =  
    Class.forName(options.valueOf(className)) 
    .asSubclass(classCI); 

साथ कोई समस्या नहीं है करना चाहते हैं? हम अनियंत्रित डाली

Class<Callable<Integer>> classCI = (Class<Callable<Integer>>)Callable.class; 

यह पूरी तरह से असुरक्षित है द्वारा धोखा कर सकते हैं। यह सुनिश्चित करने के लिए बाहरी बल होना चाहिए कि className वास्तव में Callable<Integer> है। उदाहरण के लिए यदि यह Callable<String> है, तो प्रोग्राम बिना किसी समस्या के सभी कलाकारों के माध्यम से चलता है, और यह केवल बाद में उड़ाता है जब Integer call() आक्रमण किया जाता है, और त्रुटि संदेश बहुत भ्रामक होगा।

ठीक है अगर एक डाली स्थिर विश्लेषण किया नहीं किया जा सकता सफल होने के लिए:

Object o = ...; 
String s1 = (String)o; // may fail, no javac warning 
String s2 = String.class.cast(o); // may fail, no javac warning 

जब तक एक अपवाद तुरंत फेंक दिया जाता है जब डाली कार्यावधि में विफल रहता है।

प्रकार सुरक्षा के लिए, हम सक्रिय रूप से className

@SuppressWarning("unchecked") 
Class<? Callable<Integer>> getClass(String className) 
{ 
    Class clazz = Class.forName(className); 
    via reflection, check generic super interfaces of clazz 
    if there's no Callable<Integer> super interface 
     throw "className is not a Callable<Integer>" 

    // we have *checked*, the following cast is safe 
    return (Class<? Callable<Integer>>)clazz; 
} 

के जेनेरिक प्रकार हम को दबाने के लिए यहाँ "अनियंत्रित" उचित हैं जाँच चाहिए, क्योंकि कार्यान्वयन चेकों सुनिश्चित करने के लिए कि अगर className नहीं करता है वास्तव में Callable<Integer> लागू करने वाली कक्षा को इंगित नहीं करता है, यह तुरंत वहां एक अपवाद फेंकता है। हमारी कास्ट "चेक" है, और कार्यक्रम प्रकार सुरक्षित है।

+0

+1: ओमजी, मैं वास्तव में जेनेरिक के साथ इतना फिट होना चाहता हूं ताकि मैं समझ सकूं कि यहां क्या हो रहा है। – Rekin

+0

वाह, महान जवाब। धन्यवाद, स्वीकार किया। :) – TC1

+0

बस एफवाईआई, कास्ट क्लास <कॉल करने योग्य > कक्षासीआई = (कक्षा <कॉल करने योग्य >) Callable.class किसी कारण से काम नहीं करता है। वैसे भी, चूंकि मैं प्रतिबिंब के माध्यम से कॉल करने योग्य की जांच करता हूं, इतना बड़ा सौदा नहीं, बस कुछ ऐसा सोचने के लिए जो आप इसे संपादित करना चाहते हैं। – TC1

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