有没有办法测试参数是否与方法匹配?

时间:2018-04-15 11:45:04

标签: java

我想要这样的东西

boolean match(Method method, Object... args)

如果args匹配method,则返回true,否则返回false。

例如

void func(int a, int b, String c) {}

如果method代表func,则以下调用应返回true。

match(method, 1, 2, "xxx");

以下是我目前的实施情况。

static boolean match(Method method, Object... args) {
    Class[] types = method.getParameterTypes();
    if (types.length != args.length)
        return false;
    for (int i = 0; i < args.length; i++) {
        Class acceptType = types[i];
        if (!acceptType.isInstance(args[i]))
            return false;
    }
    return true;
}

上述实施存在一些问题。 它与varags参数的方法不匹配。 如果方法将float作为参数但我传递int,则它将不匹配。 还有一些其他问题,我觉得很难解决这个问题,请告诉我如何解决问题。

1 个答案:

答案 0 :(得分:2)

您可以使用Java的 Reflection API 轻松完成此操作。它提供了分析方法签名(如参数)的方法。它甚至允许在运行时调用它们或更改代码。

请参阅以下实施:

public static boolean isApplicable(Method method, Object... args) {
    Class<?>[] parameters = method.getParameterTypes();

    // Length does not match
    if (parameters.length != args.length) {
        return false;
    }

    // Check classes against arguments
    for (int i = 0; i < args.length; i++) {
        Object argument = args[i];
        Class<?> parameterType = parameters[i];

        // Argument is not instance of parameter
        if (!parameterType.isInstance(argument)) {
            return false;
        }
    }

    return true;
}

我们使用以下方法:

实施例

假设我们有一个类

public class Foo {
    public static void bar(String text, int value) {
        System.out.println(text + ", " + value);
    }
}

您可以使用

之类的方法
Method barMethod = Foo.class.getMethod("bar", String.class, int.class);

isApplicable(barMethod, someString, someInt);               // true
isApplicable(barMethod, someString1, someString2);          // false
isApplicable(barMethod, someString1, someInt, someString2); // false

Varargs边缘案例

有一个边缘情况会使事情变得复杂一些。即,如果基础方法使用 varargs 。然后,如果长度不匹配,则需要针对参数重复测试最后Class<?>个参数:

public static boolean isApplicable(Method method, Object... args) {
    Class<?>[] parameters = method.getParameterTypes();

    // More parameters than given arguments (if varargs)
    // Different length (if not varargs)
    if ((method.isVarArgs() && parameter.length > args.length)
            || (!method.isVarArgs() && parameter.length != args.length)) {
        return false;
    }

    // Check classes against arguments
    for (int i = 0; i < args.length; i++) {
        Object argument = args[i];

        // If parameters are exhausted and method
        // is using varargs, use the last parameter
        Class<?> parameterType;
        if (method.isVarArgs() && i > parameters.length - 1) {
            parameterType = parameters[parameters.length - 1];
        } else {
            parameterType = parameters[i];
        }

        // Argument is not instance of parameter
        if (!parameterType.isInstance(argument)) {
            return false;
        }
    }

    return true;
}

对于类似

的方法
public static void bar(Object o, String... lines)

您的parameters看起来像

[Class<Object>, Class<String>]

您只需将最后一个类Class<String>重复应用于所有传入的参数。