java 如何使用可变参数和反射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2600854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 21:59:02  来源:igfitidea点击:

How to work with varargs and reflection

javareflectionvariadic-functions

提问by PeterMmm

Simple question, how make this code working ?

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

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);
    }
}

Output:

输出:

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)

回答by Bozho

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

works. The problem is that getMethod(..)only searches the publicmethods. From the javadoc:

作品。问题是getMethod(..)只搜索public方法。从javadoc:

Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.

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

Update:After successfully getting the method, you can invoke it using:

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

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

that is - create a new Objectarray with one element - the Stringarray. With your variable names it would look like:

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

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

回答by polygenelubricants

//prior to edit:

//编辑前:

Your problem is the fact that getMethodlooks for a publicmember.

你的问题是getMethod寻找public成员的事实。

From the Class.getMethod(emphasis mine):

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

Returns a Methodobject that reflects the specified publicmember method of the class or interface represented by this Class object

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

So you have two options:

所以你有两个选择:

  • Make public void foo(String... s)and use getMethod
  • Use getDeclaredMethodinstead
  • 制作public void foo(String... s)和使用getMethod
  • 使用getDeclaredMethod替代

Note that the same difference exists for getField/svs getDeclaredField/sand getConstructor/svs getDeclaredConstructor/s.

请注意,getField/svsgetDeclaredField/sgetConstructor/svs存在相同的差异getDeclaredConstructor/s



//invokeproblem

//invoke问题

This is particularly nasty, but what happens is that invoke(Object obj, Object... args)makes it tricky if you need to pass an array of reference type as an only argument, because it is cast-able to Object[], even though it should be wrapped inside a new Object[1]instead.

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

You can do:

你可以做:

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

This bypasses the vararg mechanism. More succinctly you can also do:

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

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

The cast to Objectmakes the vararg mechanism do the work of creating the array for you.

Object强制转换使可变参数机制为您完成创建数组的工作。

The trick is also needed when passing a nullas an argument to varargs, and has nothing to do with reflection.

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

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

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