public static boolean typesMatch(Class<?>[] usedTypes, Class<?>[] expectedTypes) { // expectedTypes is empty if (ArrayUtil.isEmpty(expectedTypes)) return ArrayUtil.isEmpty(usedTypes); Class<?> lastExpectedType = ArrayUtil.lastElementOf(expectedTypes); if (lastExpectedType.isArray()) { // process varargs parameter if (usedTypes.length < expectedTypes.length - 1) return false; // fault if (usedTypes.length == expectedTypes.length - 1) return typesMatch( usedTypes, ArrayUtil.copyOfRange(expectedTypes, 0, usedTypes.length)); // empty varargs // check if all used types match the varargs type if (usedTypes.length >= expectedTypes.length) { Class<?> componentType = lastExpectedType.getComponentType(); for (int i = expectedTypes.length - 1; i < usedTypes.length; i++) { Class<?> foundType = usedTypes[i]; if (!typeMatches(foundType, componentType)) return false; } return true; } } if (usedTypes.length != expectedTypes.length) return false; if (expectedTypes.length == 0 && usedTypes.length == 0) return true; for (int i = 0; i < usedTypes.length; i++) { Class<?> expectedType = expectedTypes[i]; Class<?> foundType = usedTypes[i]; if (!typeMatches(foundType, expectedType)) return false; } return true; }
/** * Finds a method by reflection. This iterates all methods of the class, comparing names and * parameter types. Unlike the method Class.getMethod(String, Class ...), this method is able to * match primitive and wrapper types. If no appropriate method is found, 'null' is returned * * @param type * @param methodName * @param paramTypes * @return a method with matching names and parameters */ public static Method findMethod(Class<?> type, String methodName, Class<?>... paramTypes) { Method result = null; for (Method method : type.getMethods()) { if (!methodName.equals(method.getName())) continue; if (typesMatch(paramTypes, method.getParameterTypes())) { result = method; if ((ArrayUtil.isEmpty(paramTypes) && ArrayUtil.isEmpty(method.getParameterTypes())) || paramTypes.length == method.getParameterTypes().length) return method; // optimal match - return it immediately else result = method; // sub optimal match - store it, but keep on searching for better matches } } return result; }