approccio Probabilmente più flessibile è quello di controllare tutti i costruttori e trovare quello compatibile in questo modo:
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;
}
Ci sono ancora questioni aperte anche se, come varargs-costruttori. Anche i casi di ambiguità non verranno risolti come fa javac (ad esempio, se hai il costruttore MyObj(Object)
e MyObj(String)
, non sarai in grado di utilizzare quest'ultimo come entrambi).
fonte
2015-11-18 09:03:09
È necessario cercare la matrice di costruttori per il costruttore i cui parametri corrispondono agli argomenti. –
Dove entra in 'AbstractClass'? Perché è necessario? –
E la firma del metodo dovrebbe essere qualcosa come 'public T getNewInstance (classe finale clazz, Object ... cs);' –
Codebender