private static <T> Constructor<T> matchingConstructor(Class<T> type, Object[] params) { final Constructor<T> ctor = ReflectionUtil.getMatchingConstructor(type, ReflectionUtil.getTypes(params)); if (ctor == null) throw new IllegalArgumentException("No constructor for type " + type.getName() + " was found to match parameters " + Arrays.toString(params)); return ctor; }
private static float getTotalTransformationCost(final Class<?>[] srcArgs, final Class<?>[] destArgs) { float totalCost = 0.0f; for (int i = 0; i < srcArgs.length; i++) { Class<?> srcClass, destClass; srcClass = srcArgs[i]; destClass = destArgs[i]; totalCost += getObjectTransformationCost(srcClass, destClass); } return totalCost; }
/** * Compares the relative fitness of two sets of parameter types in terms of * matching a third set of runtime parameter types, such that a list ordered * by the results of the comparison would return the best match first * (least). * * @param left the "left" parameter set * @param right the "right" parameter set * @param actual the runtime parameter types to match against * <code>left</code>/<code>right</code> * @return int consistent with <code>compare</code> semantics */ static int compareParameterTypes(final Class<?>[] left, final Class<?>[] right, final Class<?>[] actual) { final float leftCost = getTotalTransformationCost(actual, left); final float rightCost = getTotalTransformationCost(actual, right); return leftCost < rightCost ? -1 : rightCost < leftCost ? 1 : 0; }
public static <T> Constructor<T> getMatchingConstructor(final Class<T> cls, final Class<?>... parameterTypes) { // see if we can find the constructor directly // most of the time this works and it's much faster try { final Constructor<T> ctor = cls.getConstructor(parameterTypes); return ctor; } catch (final NoSuchMethodException e) { } // return best match: Constructor<T> result = null; final Constructor<?>[] ctors = cls.getConstructors(); for (Constructor<?> ctor : ctors) { // compare parameters if (isAssignable(parameterTypes, ctor.getParameterTypes(), true)) { if (result == null || compareParameterTypes(ctor.getParameterTypes(), result.getParameterTypes(), parameterTypes) < 0) result = (Constructor<T>) ctor; } } return result; }
private static float getObjectTransformationCost(Class<?> srcClass, final Class<?> destClass) { if (destClass.isPrimitive()) { return getPrimitivePromotionCost(srcClass, destClass); } float cost = 0.0f; while (srcClass != null && !destClass.equals(srcClass)) { if (destClass.isInterface() && isAssignable(srcClass, destClass, true)) { // slight penalty for interface match. // we still want an exact match to override an interface match, // but // an interface match should override anything where we have to // get a superclass. cost += 0.25f; break; } cost++; srcClass = srcClass.getSuperclass(); } /* * If the destination class is null, we've travelled all the way up to * an Object match. We'll penalize this by adding 1.5 to the cost. */ if (srcClass == null) { cost += 1.5f; } return cost; }
private static Type getGenericParameterType0(Class<?> cls, Class<?> genericSuper, int paramIndex) { if (!genericSuper.isAssignableFrom(cls)) return null; if (genericSuper.isInterface()) { for (Type type : cls.getGenericInterfaces()) { final Class<?> clazz = getClass(type); if (genericSuper.isAssignableFrom(clazz)) { if (genericSuper.equals(clazz)) return type instanceof ParameterizedType ? ((ParameterizedType) type).getActualTypeArguments()[paramIndex] : null; else { for (Class<?> iface : cls.getInterfaces()) { final Type res = getGenericParameterType0(iface, genericSuper, paramIndex); if (res != null) return res; } } } } return null; } else { Type type = cls.getGenericSuperclass(); assert genericSuper.isAssignableFrom(getClass(type)); if (genericSuper.equals(getClass(type))) return type instanceof ParameterizedType ? ((ParameterizedType) type).getActualTypeArguments()[paramIndex] : null; else return getGenericParameterType0(cls.getSuperclass(), genericSuper, paramIndex); } }
cls = primitiveToWrapper(cls); if (cls == null) { return false; cls = wrapperToPrimitive(cls); if (cls == null) { return false;
public static boolean isAssignable(Class<?>[] classArray, Class<?>[] toClassArray, final boolean autoboxing) { if (classArray.length != toClassArray.length) return false; for (int i = 0; i < classArray.length; i++) { if (!isAssignable(classArray[i], toClassArray[i], autoboxing)) return false; } return true; }
public static Type getGenericParameterType(Class<?> cls, Class<?> genericSuper, int paramIndex) { if (!genericSuper.isAssignableFrom(cls)) throw new IllegalArgumentException("Class " + cls.getName() + " does not implement or extend " + genericSuper.getName()); Type res = getGenericParameterType0(cls, genericSuper, paramIndex); return !(res instanceof TypeVariable) ? res : null; }