Jos*_*man 1 java reflection variadic-functions arity
我想了解使用Java反射调用变量arity方法可能会发生什么.假设我们有一个简单的方法:
void doAllTheThings(Object ... things) {
// ...which does something with all the things...
}
Run Code Online (Sandbox Code Playgroud)
我们想要动态调用它,所以我们通过反射来获取方法:
Method doItAll = Superklass.getDeclaredMethod("doAllTheThings", Object[].class);
Run Code Online (Sandbox Code Playgroud)
并传入一个数组:
Object[] allTheThings = new Object[] { "abc", true, 15 };
doItAll.invoke(allTheThings);
Run Code Online (Sandbox Code Playgroud)
现在,这似乎并不像我直觉所说的那样有效; 特别是,IllegalArgumentException当我尝试使用像这样的varargs调用方法时,我似乎得到了各种各样的阴影.
显然我在这里缺少一些东西.我的猜测是,这与变量如何被编组到varargs中有关.我发现这篇四年前的博客文章似乎在谈论同样的问题,但我无法重现那里的"成功"案例.关于这里可能会发生什么的任何想法?
Object[][]在这种情况下你需要传入一个:
Object[] allTheThings = new Object[] { "abc", true, 15 };
doItAll.invoke(o, new Object[]{allTheThings});
Run Code Online (Sandbox Code Playgroud)
原因是things编译器将单个参数转换为单个参数类型Object[],并invoke使用参数值获取数组.
考虑一个具有更多参数的方法,以使其更清晰:
void doMoreThings(Foo bar, Object ... things) { ... }
Object[] allTheThings = new Object[] { "abc", true, 15 };
doMore.invoke(o, new Object[]{new Foo(), allTheThings});
Run Code Online (Sandbox Code Playgroud)
invoke它本身被声明为采用varargs,因此您可以让编译器为您创建外部数组.但是如果你通过了它就不会这样做Object[],因为它认为你已经这样做了.所以只需从编译器中隐藏这个事实:
doItAll.invoke(o, (Object)allTheThings);
doMore.invoke(o, new Foo(), allTheThings);
Run Code Online (Sandbox Code Playgroud)
注意第一行中的强制转换,现在编译器现在不再存在已经存在的数组,因此它创建了一个数组.在第二行中,这不是必需的,因为编译器无论如何都没有其他机会.
编辑:请注意,您的代码甚至没有编译,因为您错过了使用该doAllTheThings方法传递类的实例invoke(我o在我的代码中将其命名).
| 归档时间: |
|
| 查看次数: |
1630 次 |
| 最近记录: |