2009-11-14 9 views
19

मैं इसके नाम का उपयोग करके निर्दिष्ट कक्षा का उदाहरण बनाना चाहता हूं। मेरा कोड नीचे दिखाया गया है।जेनिक्स और क्लास .forName

मुझे एक कंपाइलर चेतावनी मिलती है। क्या मैं इसे सही तरीके से कर रहा हूं? क्या कक्षा के नाम का उपयोग करना और उस प्रकार का उदाहरण प्राप्त करना भी संभव है, क्योंकि मुझे नहीं लगता कि संकलक का कोई तरीका है कि यह जानने के लिए कि किस प्रकार का होना चाहिए?

public static <T> T create(final String className) { 
    try { 
     final Class<?> clazz = Class.forName(className); 

     //WARNING: Type safety: Unchecked cast from capture#2-of ? to T 
     return (T) create(clazz); 
    } 
    catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 

public static <T> T create(final Class<T> classToCreate) { 
    final Constructor<T> constructor; 
    try { 
     constructor = classToCreate.getDeclaredConstructor(); 
     final T result = constructor.newInstance(); 
     return result; 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

धन्यवाद

उत्तर

28

मुझे लगता है कि पहली विधि कुछ इस तरह दिखना चाहिए: उन परेशान प्रकार के बिना

public static <T> T create(final String className, Class<T> ifaceClass) 
throws ClassNotFoundException { 
    final Class<T> clazz = Class.forName(className).asSubclass(ifaceClass); 
    return create(clazz); 
} 

आप एक अप-कास्ट नहीं कर सकते एक प्रकार पैरामीटर का उपयोग कर अपने टाइपकास्ट ... सुरक्षा चेतावनी।

वैसे, अगर आप उन चेतावनियों को अनदेखा करते हैं, तो निर्माण विधि कुछ वर्ग का उदाहरण बना सकती है जो कॉलर द्वारा उपयोग किए जाने वाले वास्तविक प्रकार के अनुकूल नहीं है। यह बाद में एक अप्रत्याशित ClassCastException की ओर ले जाने की संभावना है; जैसे जब आवंटित किया जाता है।


संपादित करें: @ पास्कल बताते हैं कि हमें इस संकलन को बनाने के लिए एक टाइपकास्ट जोड़ने की आवश्यकता है; अर्थात

Class<T> clazz = (Class<T>) Class.forName(className).asSubclass(ifaceClass); 

दुर्भाग्य से, हम भी एक @SuppressWarnings एनोटेशन जोड़ने की जरूरत है

+0

हाँ, इस के रूप में करीब आप जावा के साथ मिल सकता है। वास्तविक वस्तु के निर्माण के लिए अभी भी कुछ चालें की जा रही हैं, लेकिन मैं विशिष्टताओं में शामिल नहीं होने जा रहा हूं क्योंकि उन चालों को मेरी उपयोगिता कक्षा में लागू किया गया है, जैसे ही मुझे उचित पता चल रहा है वहां सभी जावा प्रोग्रामर के बीच इसे फैलाने के लिए चैनल। – Esko

+0

@Esko, Google कोड (रिलीज़ संस्करणों के लिए) और/या गीथब (वास्तविक कोड के लिए) पर विचार करें –

+0

आपको इसे अंतिम श्रेणी क्लैज = (कक्षा ) कक्षा .forName (className) संकलित करने के लिए एक कलाकार जोड़ने की आवश्यकता है। asSubclass (ifaceClass); ' –

2

मुझे लगता है कि ऐसा इसलिए है क्योंकि Class.forName(..) टी के लिए पैरामीटर नहीं किया गया है। जब आप ग्रहण स्वत: पूर्ण ट्रिगर करते हैं, तो यह clazz.newInstance() वापसी ऑब्जेक्ट मानता है। तो, कास्ट बनाए रखें और @SuppressWarnings जोड़ें। यदि आप विधि का सही ढंग से उपयोग नहीं करते हैं (यानी String str = Utils.create("java.util.ArrayList");) तो ClassCastException होगा, लेकिन यह सामान्य है।

+0

निर्माण क्लासकास्ट अपवाद नहीं फेंक देगा। कोड इसे कॉल कर सकता है, लेकिन जरूरी नहीं है। – meriton

+0

अच्छा, हाँ, लेकिन यह इस बात पर निर्भर करता है कि वह अपनी विधियों को कैसे ठीक करता है, क्योंकि अब वे संकलन नहीं करते हैं - या तो वह अपवाद को पुनर्स्थापित करता है, या शून्य (जो एनपीई का कारण बनता है) वापस लौटाता है – Bozho

2

दूसरी विधि ठीक है।


लेकिन पहले के लिए, किसी भी वर्ग का नाम पैरामीटर के रूप में पारित किया जा सकता है।

विधि का बिंदु एक वर्ग को इंस्टाल करना होगा कि कॉलिंग कोड संकलन समय पर नहीं जानता है, यह केवल रनटाइम पर इसके बारे में जानता है।

इन परिस्थितियों में, बुला कोड, प्रकार पैरामीटर निर्धारित नहीं कर सकते तो विधि, पैरामिट्रीकृत नहीं किया जा सकता इसलिए डाली कोई मतलब नहीं है ...

इसलिए, मैं कहूंगा कि पूरे विधि कोई मतलब नहीं है


कुछ बिंदु विधि करने के लिए दिया जा सकता है अगर बुला कोड वर्ग के महाप्रकार पता होगा। इसे पैरामीटर के रूप में पारित किया जा सकता है, और कलाकार संभव और सार्थक होगा।

public static <T> T create(final Class<T> superType, final String className) { 
    try { 
    final Class<?> clazz = Class.forName(className); 
    final Object object = clazz.newInstance(); 
    if (superType.isInstance(object)) { 
     return (T)object; // safe cast 
    } 
    return null; // or other error 
    } // catch and other error code 
} 
+0

विधि क्लास.कास्ट (ऑब्जेक्ट) विधि देखें। – meriton

+0

(कम कोड प्राप्त करने के लिए, और उस अनचेक चेतावनी को खत्म करने के लिए) – meriton

+0

@Meriton True, यदि असंभव कलाकार की रिपोर्ट करने के लिए चुना गया त्रुटि क्लासकास्ट अपवाद को फेंकना है। उदाहरण के लिए, यह कोड शून्य, एक अलग विकल्प देता है ... एक विकल्प बनाया जाना चाहिए ... ;-) – KLE

0

भले ही आप काम करने के लिए ऊपर कोड प्राप्त कर सकें, कन्स्ट्रक्टर की नईInstance() विधि शून्य तर्क कन्स्ट्रक्टर मानती है।

यदि कक्षा में कोई नहीं है I।ई जिस वर्ग को आप बनाने की कोशिश कर रहे हैं उसके शून्य तर्क कन्स्ट्रक्टर को स्पष्ट रूप से निजी घोषित किया गया है, या जिस तरीके से विधि कहा जाता है, उसके आधार पर पैकेज, आपको एक अवैध एक्सेस अपवाद प्राप्त होगा। अगर आप इसे काम कर रहे हैं, तो अपनी पूर्व शर्त में कुछ जोड़ना है।

1

आप श्रेणी नाम नाम के प्रकार को रखने के लिए एक प्रकार पैरामीटर को प्रतिबंधित नहीं कर सकते हैं। इसलिए, एक कॉलर आपके निर्माण (स्ट्रिंग) फ़ंक्शन में किसी भी प्रकार की आपूर्ति कर सकता है, जो निश्चित रूप से सुरक्षित नहीं है।

चूंकि आप स्थाई रूप से लागू नहीं कर सकते हैं कि लौटाया गया उदाहरण किसी भी इंटरफ़ेस को लागू करता है (कॉलर को संबंधित क्लास ऑब्जेक्ट पास करके आपको बताए बिना), मैं जेनेरिक के साथ बांटता हूं, और कॉलर को जो कुछ भी उम्मीद है उसे कास्ट किया जाता है।

public static Object create(final String className) { 
    try { 
     final Class<?> clazz = Class.forName(className); 
     return create(clazz); 
    } 
    catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
} 

एक फोन करने वाले तो लिख सकते हैं: अगर यह एक सामान्य प्रकार नहीं है TypeClass सीधे करने के लिए परिवर्तित किया जा सकता:

Foo foo = (Foo) create("my.cool.FooBar"); 

रूप

Foo foo = create("my.cool.FooBar", Foo.class); 
0

करने का विरोध किया मैं एक दिलचस्प बात पाया । लेकिन मैं अभी भी Class.forName("java.util.List<SomeType>") नहीं कर सकता।

import java.lang.reflect.*; 
import java.util.*; 

public class Main { 
    public void func(List<List<String>> listlist, Map<String, List<String>> list, String s) {} 

    public static void main(String[] args) throws ClassNotFoundException { 
     Method m = Main.class.getDeclaredMethods()[1]; 

     Type t0 = m.getGenericParameterTypes()[0]; 
     boolean b0 = t0 instanceof Class; 

     boolean b01 = ((ParameterizedType)t0).getRawType() instanceof Class; 

     Type t1 = m.getGenericParameterTypes()[2]; 
     boolean b1 = t1 instanceof Class; 
    } 
} 

enter image description here

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