【问题标题】:Invoking method using reflection / Converting List to Var Args使用反射调用方法/将列表转换为 Var Args
【发布时间】:2011-06-16 07:50:34
【问题描述】:

我有一个参数列表和方法名称。我想使用反射调用该方法。 当我检查 java 文档中的 Method.invoke 时,它​​类似于 Method.invoke(object o, Object args...) 。 我知道要为第一个参数传递什么(即,如果是实例方法,则调用哪个方法的实例),而 args 是该方法的参数。

但是现在我有了一个包含要传递给方法的值的列表。

例如:我想调用方法 ClassName.methodName(String , int, int) 并且我有一个包含 {val1, 3, 4} 的列表。

使用反射可能类似于 Method.invoke (classNameInstance, ??????)。但我不确定如何将参数列表转换为可变参数并通过。

一种方法可能是如果我知道列表大小为 3,那么我可以编写 Method.invoke (classNameInstance, list.get(0), list.get(1), list.get(2))。

但是我想动态调用的一些方法需要 0 到 12 个参数。因此,创建 switch case 并编写 12 个 case 看起来并不“好”。每个都将检查参数数量并使用参数构建单独的调用。

除了使用 switch case 有什么办法吗?

任何帮助将不胜感激。

【问题讨论】:

    标签: java list reflection invoke variadic-functions


    【解决方案1】:

    Notation Object... 仅表示 Object[]。它只是 Arraynotation 的语法糖。传递一个数组,它就会工作。

    【讨论】:

    • 非常感谢 method.invoke(classNameInstance, argumentsList.toArray());会工作....
    • 事实上我试过这个,如果一个简单类型的列表很好用。但是说当 API 是 (String, int, int) 和 List : {"val1", "2","3"} 。将它们转换为数组后,由于类型不匹配而导致问题。意味着在我可以直接将它们传递给调用方法之前,我需要将它们类型转换为与该方法匹配的特定类型。如果是这样,我不能直接转换为数组并使用。如果我弄错了,请纠正我。
    【解决方案2】:

    已编辑:这是一种更通用的方法,适用于任何类型的可变参数:

            Class<?> c = int.class;
            Object array = Array.newInstance(c, list.size());
            for (int i = 0; i < list.size(); i++)
                    Array.set(array, i, list.get(i));
            Test.class.getDeclaredMethod("test", array.getClass()).invoke(
                    new Test(), new Object[] { array });
    

    void m(X...p)void m(X[] p) 具有相同的签名。您不能在同一个类中同时声明两者。

    以下是如何使用反射(原始和非原始)调用它们:

    import java.util.*;
    import java.lang.reflect.*;
    
    class Test
    {
            public static void main(String[] args) throws Exception
            {
                    List<Integer> list = new ArrayList<Integer>();
                    list.add(1); list.add(2); list.add(3);
                    Test.class.getDeclaredMethod("test", Integer[].class).invoke(
                        new Test(), new Object[] { list.toArray(new Integer[0]) });
                    int[] params = new int[list.size()];
                    for (int i = 0; i < params.length; i++) params[i] = list.get(i);
                    Test.class.getDeclaredMethod("test", int[].class).invoke(
                        new Test(), new Object[] { params });
            }
    
            public void test(int ... i) { System.out.println("int[]: " + i[0] + ", " + i[1] + ", " + i[2]); }
            public void test(Integer... i) { System.out.println("Integer[]" + Arrays.asList(i)); }
    }
    

    【讨论】:

    • 谢谢,但这适用于 int,但是这个 List 类型列表会出现转换问题,并且会产生类型不匹配。
    • 添加了带有任何类型可变参数的示例 -- Class> c = int.class 或任何你想要的。
    【解决方案3】:

    Varargs 实际上只是一个数组。

    方法可以这样检索,假设取int...args:

    Method method = MyClass.class.getMethod("someMethod", int[].class);
    method.invoke(myInstance, argumentsList.toArray());
    

    【讨论】:

    • List.toArray() 将返回 Object[] -- 不适用于 "int..."
    猜你喜欢
    • 1970-01-01
    • 2016-09-20
    • 2023-03-09
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多