क्या आपके पास इस तरह की विधि लिखने के बारे में कोई सुराग है?

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");
5
PRowLeR 18 नवम्बर 2015, 11:11

2 जवाब

सबसे बढ़िया उत्तर

Class विधि में Class की एक विधि होती है, जो कंस्ट्रक्टर के तर्कों के अनुरूप 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);
}

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

2
WilQu 18 नवम्बर 2015, 08:52

संभवतः अधिक लचीला दृष्टिकोण सभी निर्माणकर्ताओं की जांच करना और संगत को इस तरह खोजना है:

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-constructors। इसके अलावा अस्पष्टता के मामलों को हल नहीं किया जाएगा, जैसे कि यह javac द्वारा किया जाता है (उदाहरण के लिए, यदि आपके पास MyObj(Object) और MyObj(String) कंस्ट्रक्टर हैं, तो आप बाद वाले दोनों का उपयोग नहीं कर पाएंगे)।

3
Tagir Valeev 18 नवम्बर 2015, 09:03