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; }