gpt4 book ai didi

java - 为什么反射调用方法需要将可变参数包装在数组中?

转载 作者:行者123 更新时间:2023-12-02 08:29:33 26 4
gpt4 key购买 nike

接听this other question关于 S.O. ,我遇到了这个我无法理解的奇怪问题。为什么 Method 类的反射“调用”方法需要将 varargs 参数包装在数组中才能工作?

其他带有 vararg 参数的类方法只需以正常方式调用它们即可正常运行...

public class Main {
public static void main(String[] args){


try {
Class<?> p = Main.class;

String[] arguments1 = {"ciao"};
String[] arguments2 = {"salve"};
String[] arguments3 = {"buonasera"};

Method m = p.getDeclaredMethod("showIt",String[].class);


//this is ok
showIt(arguments1);

//this is ok
m.invoke(null, new Object[]{arguments2});

//this throws IllegalArgumentException!!
m.invoke(null, arguments3);

} catch (Exception e) {
e.printStackTrace();
}
}

public static void showIt(String[] result) {
System.out.println(result[0]);
}


}

invoke方法有什么特别之处?

最佳答案

这是因为这里关于可变参数和数组参数类型存在歧义。基本上,当一个方法声明为

void takesSomeArgs(Object... values) {
}

这基本上相当于

void takesSomeArgs(Object[] values) {
}

问题是,现在对以下调用有两种潜在的(并且同样有效的)解释:

Object[] example = { "foo", "bar" };
takesSomeArgs(example);

第一个解释是

  • 使用单个参数值调用该方法,即 values 类似于 Object[1] { Object[1] { "foo", "bar"} }(可变参数解释)
  • 使用两个参数值调用该方法,即 values 类似于 Object[2] { "foo", "bar"},因为 Object ... 本质上是 Object[],因此,我们可以直接将 example 中的数组引用作为 value 的值传递>.

根据 JLS 15.12.2.3 的规则,编译器订阅第二种解释(在调用 invoke(Object, Object...) 本身时,它是可变参数),这会导致尝试传递 two 你的方法的参数——失败了,因为该方法只需要一个(编辑注意,我在这里描述了错误的症状;请参阅 Json 的答案,它是正确的)。换句话说,这样的调用:

m.invoke(receiver, new Object[] { "a", "b", "c" });

m.invoke(receiver, "a", "b", "c");

实际上是同一件事。因此需要写

m.invoke(receiver, new Object[] { new Object[] { "a", "b", "c" } });  // (X)

(明确)或

m.invoke(receiver, (Object) (new Object[] { "a", "b", "c" }));

注意强制转换:它使参数不再可转换为 Object[] 并强制编译器生成与 (X) 等效的代码。另请注意,new Object[] { ... } 不能按字面意思理解,而只是为了使所涉及的值的类型变得清晰。

在我看来,这是一个不幸的副作用,Java 语言的设计者希望使实现类似的东西成为可能(并且方便)

void logError(String control, Object... parameters) {
// Forwarding the unknown number of arguments from one variadic method
// to the next: String.format(String, Object...)
log.message(String.format(control, parameters));
}

无需引入新语法。

关于java - 为什么反射调用方法需要将可变参数包装在数组中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17093615/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com