代码之家  ›  专栏  ›  技术社区  ›  PeterMmm

如何处理varargs和反射

  •  24
  • PeterMmm  · 技术社区  · 14 年前

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

    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)
    
    2 回复  |  直到 14 年前
        1
  •  45
  •   Bozho    14 年前
    Test.class.getDeclaredMethod("foo", String[].class);
    

    作品。问题是 getMethod(..) 只搜索 public 方法。来自JavaDoc:

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

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

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

    那就是-创造一个新的 Object 带一个元素的数组 String 数组。对于变量名,它看起来像:

    m.invoke(this, new Object[] {a});
    
        2
  •  9
  •   polygenelubricants    14 年前

    //编辑前:

    你的问题是 getMethod 寻找一个 public 成员。

    Class.getMethod (重点是我的):

    返回A Method 反映指定的 公众的 此类对象表示的类或接口的成员方法

    所以你有两个选择:

    • 制作 public void foo(String... s) 使用 获取方法
    • 使用 getDeclaredMethod 相反

    请注意,对于 getField/s VS getDeclaredField/s getConstructor/s VS getDeclaredConstructor/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);
    

    演员阵容 Object 使vararg机制完成为您创建数组的工作。

    当通过一个 null 作为varargs的参数,与反射无关。

    public void foo(String... ss) {
        System.out.println(ss[0]);
    }
    
        foo(null); // causes NullPointerException
        foo((String) null); // prints "null"