2011-11-23 13 views
6

मैं कंक्रीट उप-वर्गों के उदाहरणों को वापस करने के लिए एक अमूर्त कारखाने का उपयोग कर रहा हूं। मैं कंक्रीट क्लास नाम के स्ट्रिंग को दिए गए रनटाइम पर सबक्लास को तुरंत चालू करना चाहता हूं। मुझे कन्स्ट्रक्टर को पैरामीटर पास करने की भी आवश्यकता है। java.lang.NoSuchMethodException: Child.<init>(), स्टैक ट्रेस द्वारा पीछा किया:पैरामीटर पर जावा इंस्टेंटिएट क्लास पैरामीटर

abstract class Parent { 

    private static HashMap<String, Child> instances = new HashMap<String,Child>() 

    private Object constructorParameter; 

    public static Child factory(String childName, Object constructorParam){ 

    if(instances.keyExists(childName)){ 
     return instances.get(childName); 
    } 

    //Some code here to instantiate the Child using constructorParam, 
    //then save Child into the HashMap, and then return the Child. 
    //Currently, I am doing: 
    Child instance = (Child) Class.forName(childClass).getConstructor().newInstance(new Object[] {constructorParam}); 
    instances.put(childName, instance); 
    return instance; 
    } 

    //Constructor is protected so unrelated classes can't instantiate 
    protected Parent(Object param){ 
    constructorParameter = param; 
    } 

}//end Parent 

class Child extends Parent { 
    protected Child(Object constructorParameter){ 
     super(constructorParameter); 
    } 
} 

मेरे attmept ऊपर निम्न अपवाद फेंक है: वर्ग संरचना इस प्रकार है।

किसी भी मदद की सराहना की जाती है। धन्यवाद!

उत्तर

13
Constructor<?> c = Class.forName(childClass).getDeclaredConstructor(constructorParam.getClass()); 
c.setAccessible(true); 
c.newInstance(new Object[] {constructorParam}); 

getConstructor विधि निर्माताओं के बीच भेद करने के Class तर्क लेता है। लेकिन यह केवल सार्वजनिक रचनाकारों को लौटाता है, इसलिए आपको getDeclaredConstructor(..) की आवश्यकता होगी। तो आपको setAccessible(true)

+0

मैं इस कोशिश की और अब भी वही त्रुटि देख रहा हूँ में जोड़ें। क्या मुझे किसी भी कन्स्ट्रक्टर हस्ताक्षर बदलने की ज़रूरत है? फिलहाल हस्ताक्षर स्पष्ट रूप से ऑब्जेक्ट के पैरामीटर की अपेक्षा नहीं करते हैं, लेकिन कुछ और विशिष्ट हैं। – bibs

+0

आपके 'constructorParam.getClass() 'को – Bozho

+0

की अपेक्षा कर रहे सटीक पैरामीटर प्रकार को वापस करना चाहिए, उदाहरण के लिए, मुझे यकीन नहीं है कि creatorParam.getClass() क्या करता है। क्या आप अपने उत्तर को बेहतर समझा सकते हैं? धन्यवाद! – trusktr

3

त्रुटि: आप गलत निर्माता का आह्वान कर रहे हैं - और कंपाइलर के पास आपकी सहायता करने का कोई तरीका नहीं है।

आपकी समस्या यह थी कि आप तर्क के साथ एक के बजाय शून्य-तर्क कन्स्ट्रक्टर तक पहुंच रहे थे। याद रखें कि जावा में कन्स्ट्रक्टर आखिरकार सिर्फ विधियों हैं, यद्यपि विशेष वाले हैं - और प्रतिबिंब के साथ, सभी दांव बंद हैं --- अगर आप कुछ मूर्खतापूर्ण करते हैं तो संकलक आपकी मदद नहीं करेगा। आपके मामले में, आपके पास एक स्कोप समस्या थी और एक ही समय में एक विधि हस्ताक्षर समस्या थी।

कैसे इस समस्या को हल करने के लिए और एक अच्छा विचार इस आवेदन

इसके बाद पुन: इसके साथ सौदा करने के लिए एक स्थिर सहायक विधि है कि सीधे परीक्षण किया हो सकता है में निर्माता आमंत्रण रैप करने के लिए, और फिर डाल की आवश्यकता नहीं है मेरे यूनिट परीक्षणों में स्पष्ट रूप से उनके लिए एक परीक्षण, क्योंकि यदि निर्माता बदलता है और आप अपने प्रतिबिंब कोड को अपडेट करना भूल जाते हैं, तो आप फिर से इन गुप्त त्रुटियों को फिर से देखेंगे।

तुम भी बस के रूप में निम्नानुसार निर्माता आह्वान कर सकते हैं:

public static Child create(Integer i, String s) throws Exception 
{ 
    Constructor c = Class.forName(childClass).getConstructor(new Object[]{Integer.class, String.class}); 
    c.setAccessible(true); 
    Child instance = (Child) c.newInstance(new Object[]{i , s}) ; 
    return instance; 
} 

और निश्चित रूप से अपने परीक्षण

@Test 
    public void testInvoke() 
    { 
     try{ 
    MyClass.create(1,"test"); 
    } 
    catch(Exception e) 
    { 
     Assert.fail("Invocation failed : check api for reflection classes in " + MyClass.class); 
    } 
    } 
+0

आप वास्तव में यहां निर्माता को पैरामीटर कहां पास करते हैं? – bibs

+0

@bibs क्षमा करें मैंने उस "मामूली" जानकारी को छोड़ दिया। पाठ्यक्रम का गतिशील कन्स्ट्रक्टर आमंत्रण एक ऑब्जेक्ट सरणी को अपने तर्क के रूप में लेता है, जो क्लास.getConstructor ... विधि से प्राप्त कन्स्ट्रक्टर हस्ताक्षर से मेल खाना चाहिए। – jayunit100

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