/** * Find an accessible constructor with compatible parameters. Compatible parameters mean that * every method parameter is assignable from the given parameters. In other words, it finds * constructor that will take the parameters given. * * <p>First it checks if there is constructor matching the exact signature. If no such, all the * constructors of the class are tested if their signatures are assignment compatible with the * parameter types. The first matching constructor is returned. * * @param cls find constructor for this class * @param parameterTypes find method with compatible parameters * @return a valid Constructor object. If there's no matching constructor, returns <code>null * </code>. */ public static Constructor getMatchingAccessibleConstructor(Class cls, Class[] parameterTypes) { // see if we can find the constructor directly // most of the time this works and it's much faster try { Constructor ctor = cls.getConstructor(parameterTypes); MemberUtils.setAccessibleWorkaround(ctor); return ctor; } catch (NoSuchMethodException e) { /* SWALLOW */ } Constructor result = null; // search through all constructors Constructor[] ctors = cls.getConstructors(); for (int i = 0; i < ctors.length; i++) { // compare parameters if (ClassUtils.isAssignable(parameterTypes, ctors[i].getParameterTypes(), true)) { // get accessible version of method Constructor ctor = getAccessibleConstructor(ctors[i]); if (ctor != null) { MemberUtils.setAccessibleWorkaround(ctor); if (result == null || MemberUtils.compareParameterTypes( ctor.getParameterTypes(), result.getParameterTypes(), parameterTypes) < 0) { result = ctor; } } } } return result; }
/** * Find an accessible method that matches the given name and has compatible parameters. Compatible * parameters mean that every method parameter is assignable from the given parameters. In other * words, it finds a method with the given name that will take the parameters given. * * <p> * * <p>This method is used by {@link #invokeMethod(Object object, String methodName, Object[] args, * Class[] parameterTypes)}. * * <p>This method can match primitive parameter by passing in wrapper classes. For example, a * <code>Boolean</code> will match a primitive <code>boolean</code> parameter. * * @param cls find method in this class * @param methodName find method with this name * @param parameterTypes find method with most compatible parameters * @return The accessible method */ public static Method getMatchingAccessibleMethod( Class cls, String methodName, Class[] parameterTypes) { try { Method method = cls.getMethod(methodName, parameterTypes); MemberUtils.setAccessibleWorkaround(method); return method; } catch (NoSuchMethodException e) { /* SWALLOW */ } // search through all methods Method bestMatch = null; Method[] methods = cls.getMethods(); for (int i = 0, size = methods.length; i < size; i++) { if (methods[i].getName().equals(methodName)) { // compare parameters if (ClassUtils.isAssignable(parameterTypes, methods[i].getParameterTypes(), true)) { // get accessible version of method Method accessibleMethod = getAccessibleMethod(methods[i]); if (accessibleMethod != null) { if (bestMatch == null || MemberUtils.compareParameterTypes( accessibleMethod.getParameterTypes(), bestMatch.getParameterTypes(), parameterTypes) < 0) { bestMatch = accessibleMethod; } } } } } if (bestMatch != null) { MemberUtils.setAccessibleWorkaround(bestMatch); } return bestMatch; }