如何使用变色和反射

2022-09-01 18:15:39

简单的问题,如何使这段代码工作?

public class T {

    public static void main(String[] args) throws Exception {
        new T().m();
    }

    public // as mentioned by Bozho
    void foo(String... s) {
        System.err.println(s[0]);
    }

    void m() throws Exception {
        String[] a = new String[]{"hello", "kitty"};
        System.err.println(a.getClass());
        Method m = getClass().getMethod("foo", a.getClass());
        m.invoke(this, (Object[]) a);
    }
}

输出:

class [Ljava.lang.String;
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)

答案 1
Test.class.getDeclaredMethod("foo", String[].class);

工程。问题是只搜索方法。来自 javadoc:getMethod(..)public

返回一个 Method 对象,该对象反映此类对象所表示的类或接口的指定公共成员方法。

更新:成功获取该方法后,您可以使用以下命令调用它:

m.invoke(this, new Object[] {new String[] {"a", "s", "d"}});

即 - 创建一个具有一个元素的新数组 - 数组。使用变量名称,它看起来像这样:ObjectString

m.invoke(this, new Object[] {a});

答案 2

编辑前:

您的问题是寻找成员的事实。getMethodpublic

来自 Class.getMethod(强调我的):

返回一个对象,该对象反映由此类对象表示的类或接口的指定公共成员方法Method

因此,您有两种选择:

  • 制造和使用public void foo(String... s)getMethod
  • 请改用getDeclaredMethod

请注意,对于 vs 和 vs 存在相同的差异。getField/sgetDeclaredField/sgetConstructor/sgetDeclaredConstructor/s


//invoke问题

这是特别令人讨厌的,但是如果你需要将引用类型的数组作为唯一的参数传递,那么它就会变得棘手,因为它是可以强制转换的,即使它应该被包装在一个中。invoke(Object obj, Object... args)Object[]new Object[1]

您可以执行以下操作:

m.invoke(this, new Object[] {a}); // Bohzo's solution

这绕过了 vararg 机制。更简洁地说,您还可以执行以下操作:

m.invoke(this, (Object) a);

使 vararg 机制执行为您创建数组的工作。Object

在将 a 作为参数传递给 varargs 时,也需要这个技巧,并且与反射无关。null

public void foo(String... ss) {
    System.out.println(ss[0]);
}

    foo(null); // causes NullPointerException
    foo((String) null); // prints "null"