java - 想要在运行时 java 中动态传递 class.getmethod 参数

标签 java reflection overloading

我想通过在运行时提供 methodName 来调用方法。我可以通过以下方式做到这一点。

Method method = MyObject.class.getMethod("doSomething", String.class);
Object returnValue = method.invoke(null, "parameter-value1");

但我想列出所有具有该方法名称和不同参数集的重载方法,让用户选择一个特定的重载方法并动态传递这些参数

Method method = MyObject.class.getMethod("doSomething", String.class);

而不是硬编码 String.class

假设我有两种方法

methodName(String) 

和重载方法

methodName(String, int)

我想让用户选择在运行时选择哪一个,并将该信息传递给该特定方法的 getMethod 函数。

我该怎么做?

最佳答案

我们有一个方法叫做 Class.forName(String) 加载 Class<?> 的实例通过它的名字。

问题是我们必须传递所需类的完全限定名称(包括包的名称)。这意味着 Class.forName("String")是行不通的。相反,我们需要将其称为 Class.forName("java.lang.String") .

我们可以有一个映射(或枚举)来保存那些 Class<?> es。由于我们希望用户进行协作,因此键为 String s 和结构就像 Map<String, Class<?>> :

user > string
we   < class java.util.String

然后,我们应该弄清楚如何根据类型解析方法参数——它们将以 String 的形式出现。秒。我会使用 Function<String, ?>每种类型:

Function<String, T> converter = (String s) -> T.convertFromString(s);

为了让您更清楚,我为您写了一个简单、完整的示例:

class Test {
    // prints s once
    public static void method(String s) {
        System.out.println(s);
    }

    // prints s i times
    public static void method(String s, int i) {
        System.out.println(IntStream.rangeClosed(0, i - 1)
                .mapToObj($ -> s)
                .collect(Collectors.joining(" ")));
    }

    public static void main(String[] args) {
        perform();
    }

    public static Object perform() {
        final Scanner scanner = new Scanner(System.in);

        // read the method name
        final String methodName = scanner.nextLine();

        final Method[] methods = Arrays.stream(Test.class.getDeclaredMethods())
                .filter(m -> m.getName().endsWith(methodName) && !m.isSynthetic())
                .toArray(Method[]::new);

        // read the method parameter types in the format "type1 type2"
        final String rawMethodParametersTypes = scanner.nextLine();

        final SupportedType[] methodParameterTypes = Arrays.stream(rawMethodParametersTypes.split(" "))
                .map(p -> SupportedType.valueOf(p.toUpperCase()))
                .toArray(SupportedType[]::new);

        final Optional<Method> selectedMethod = Arrays.stream(methods)
                .filter(m -> Arrays.equals(Arrays.stream(methodParameterTypes)
                        .map(SupportedType::getType).toArray(Class<?>[]::new), m.getParameterTypes()))
                .findAny();

        if (!selectedMethod.isPresent()) {
            return null;
        }

        final Method method = selectedMethod.get();

        // read method arguments in the format "arg1 arg2"
        final String rawMethodArgumentsLine = scanner.nextLine();
        final String[] rawMethodArguments = rawMethodArgumentsLine.split(" ");

        final int expectedLength = method.getParameterCount();
        if (rawMethodArguments.length != expectedLength) {
            return null;
        }

        Object[] methodArguments = new Object[expectedLength];
        for (int i = 0; i < expectedLength; ++i) {
            methodArguments[i] = methodParameterTypes[i].getConverter().apply(rawMethodArguments[i]);
        }

        try {
            return method.invoke(null, methodArguments);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        return null;
    }
}

我介绍了一个枚举 SupportedType声明我们将支持的类型以及用户在选择签名时可能遇到的类型。

@RequiredArgsConstructor
public enum SupportedType {
    STRING(String.class, s -> s),
    INT(int.class, Integer::valueOf);

    @Getter
    private final Class<?> type;

    @Getter
    private final Function<String, Object> converter;
}

以下是 method(String, int) 的输入输出示例

> method
> string int
> hello 5
< hello hello hello hello hello

method(String)

> method
> string
> hello
< hello

关于java - 想要在运行时 java 中动态传递 class.getmethod 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51581285/

相关文章:

python,没有方法重载,howto?

c++ - 为什么具有相同名称但不同签名的多重继承函数不被视为重载函数?

java - 如何使用 Selenium 修复 Edge 浏览器中的 ElementNotVisibleException?

c# - 如何在我的程序中使用 .NET 类型字符串?

没有指定参数的Java/Taking方法

python - 在 Python 中使用参数调用对象的方法

c# - 抽象类中 'this'的类型与重载方法解析顺序困惑

java - MVC 验证数据

java - 依赖注入(inject) : Scoping by region (Guice, Spring,随便)

java - socket接收端打印时分割数据