2015-11-18 22 views
5

के साथ पैरामीटर सूची के बजाय ऑब्जेक्ट [] को पास करके कक्षा के नए उदाहरण को कैसे बनाएं, क्या आपको इस तरह की विधि लिखने के बारे में कोई जानकारी है?प्रतिबिंब

public abstract class AbstractClass{} 

public class TrialClass extends AbstractClass{ 
    public TrialClass(final String a, final String b){} 
    public TrialClass(final String a, final String b, final String c){} 
} 

public class getNewInstance(final Class<? extends AbstractClass> clazz, Object... constructorParameters){ 
    //??? 
} 

TrialClass trialClass = getNewInstance(TrialClass.class, "A", "B"); 
+0

आपको कन्स्ट्रक्टर के लिए कन्स्ट्रक्टर की सरणी खोजनी है जिसका पैरामीटर तर्क से मेल खाता है। –

+0

'सार तत्व' कहां से आता है? इसकी आवश्यकता क्यों है? –

+0

और आपकी विधि हस्ताक्षर कुछ सार्वजनिक होना चाहिए जैसे 'सार्वजनिक <टी सार क्लास> टी getNewInstance (अंतिम कक्षा क्लैज, ऑब्जेक्ट ... सीएस); ' – Codebender

उत्तर

2

Class विधि एक getConstructor विधि है कि एक पैरामीटर के रूप Class की एक सरणी लेता है, निर्माता तर्क करने के लिए इसी में शामिल है। आपको इस पैरामीटर को अपने पैरामीटर सरणी से बनाना होगा।

कुछ इस तरह:

public <T> T getNewInstance(final Class<T> clazz, Object... constructorParameters) throws InstantiationException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException{ 
    Class[] parameterTypes = new Class[constructorParameters.length]; 
    for(int i = 0; i < constructorParameters.length; i++) { 
     parameterTypes[i] = constructorParameters[i].getClass(); 
    } 

    Constructor<T> constructor = clazz.getConstructor(parameterTypes); 
    return constructor.newInstance(constructorParameters); 
} 

संपादित करें: के रूप में Codebender ने कहा, यह जब एक उप-प्रकार तर्क के रूप में पारित हो जाता है काम नहीं करता।

+1

यह तब काम नहीं करता है जब कोई सबटाइप तर्क के रूप में पारित हो जाता है ... – Codebender

+0

थैला भाग जो कि कन्स्ट्रक्टर को सही बनाता है, सही है, लेकिन नए इंस्टेंस को बनाने के लिए तर्क पारित करने में कुछ समस्याएं हैं। अगर हम इस विधि को कॉल करते हैं जैसे: getNewInstance (TrialClass.class, "ए", "बी"); कन्स्ट्रक्टर पैरामीटर एक ऑब्जेक्ट सरणी होगा जिसमें "ए" और "बी" होगा। तो हम स्ट्रिंग, स्ट्रिंग पैरामीटर के बजाय ऑब्जेक्ट एरे पास करने का प्रयास कर रहे हैं। यह कोड शायद IllegalArgumentException फेंक देगा। – PRowLeR

+0

constructor.newInstance (कन्स्ट्रक्टर पैरामीटर [0], कन्स्ट्रक्टर पैरामीटर [1]) उस उदाहरण के लिए काम करेंगे। – PRowLeR

3

शायद और अधिक लचीला दृष्टिकोण सभी निर्माताओं की जाँच करें और इस तरह से संगत एक मिल रहा है:

public static <T> T getNewInstance(final Class<T> clazz, Object... constructorParameters) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
    Constructor<?> candidate = null; 
    for(Constructor<?> constructor : clazz.getConstructors()) { 
     if(Modifier.isPublic(constructor.getModifiers()) && isConstructorCompatible(constructor, constructorParameters)) { 
      if(candidate == null) 
       candidate = constructor; 
      else 
       throw new IllegalArgumentException("Several constructors found which are compatible with given arguments"); 
     } 
    } 
    if(candidate == null) 
     throw new IllegalArgumentException("No constructor found which is compatible with given arguments"); 
    return (T) candidate.newInstance(constructorParameters); 
} 

private static boolean isConstructorCompatible(Constructor<?> constructor, Object[] constructorParameters) { 
    Class<?>[] parameterTypes = constructor.getParameterTypes(); 
    if(parameterTypes.length != constructorParameters.length) 
     return false; 
    for(int i=0; i<parameterTypes.length; i++) 
     if(!isParameterCompatible(parameterTypes[i], constructorParameters[i])) 
      return false; 
    return true; 
} 

private static boolean isParameterCompatible(Class<?> type, Object parameter) { 
    if(parameter == null) 
     return !type.isPrimitive(); 
    if(type.isInstance(parameter)) 
     return true; 
    if(type.isPrimitive()) { 
     if (type == int.class && parameter instanceof Integer 
       || type == char.class && parameter instanceof Character 
       || type == byte.class && parameter instanceof Byte 
       || type == short.class && parameter instanceof Short 
       || type == long.class && parameter instanceof Long 
       || type == float.class && parameter instanceof Float 
       || type == double.class && parameter instanceof Double 
       || type == boolean.class && parameter instanceof Boolean) 
      return true; 
    } 
    return false; 
} 

वहाँ अभी भी खुला मुद्दों हालांकि तरह varargs-निर्माता ये हैं। इसके अलावा अस्पष्टता के मामलों को हल नहीं किया जाएगा जैसे कि जैवैक द्वारा किया गया है (उदाहरण के लिए, यदि आपके पास MyObj(Object) और MyObj(String) कन्स्ट्रक्टर है, तो आप बाद वाले का उपयोग करने में सक्षम नहीं होंगे दोनों मैच हैं)।