【问题标题】:Distinguish if method has arbitrary number of parameters through reflection通过反射区分方法是否具有任意数量的参数
【发布时间】:2019-07-09 05:25:50
【问题描述】:

在使用反射调用的时候,有什么办法可以区分这两种方法吗?

public void method(Object[] args) {}

public void method(Object... args) {}

【问题讨论】:

  • 您的问题尚无定论,因为此代码甚至无法编译。它失败并显示错误消息error: cannot declare both method(Object...) and method(Object[])See this demo.
  • 显然这段代码无法编译。问题是如何区分该方法是否以一种方式或另一种方式声明
  • 基于无法编译,我假设两个签名在运行时会显示相同,即Object[]。但是,为什么您需要知道其中的区别?
  • 因为我收到了一个对象数组,并且我想在调用可以使用接收到的参数调用它的方法之前知道。如果我有一个 Object[] 参数,我只能有 1 个参数;否则,我可以有 3 个甚至 0 个参数。
  • 不,你不能。这就是人们一次又一次地试图告诉你的。运行时没有可变参数。如果你打算使用反射调用可变参数方法,你必须传递一个数组!

标签: java reflection


【解决方案1】:

您可以通过Parameter#isVarArgs() 测试Parameter 是否为可变参数。

如果此参数表示变量参数列表,则返回true;否则返回false


Executable 接口有一个 similar methodConstructorMethod 都实现了它。

如果此可执行文件被声明为采用可变数量的参数,则返回true;否则返回false


但是,如果我正确理解为什么你会问这个问题,那么知道这些信息对你没有帮助。参数是否为可变参数不会影响您调用Method#invoke 的方式。正如 GhostCat 提到并由 Ferrybig 暗示的那样,无论哪种方式,您都需要传递一个数组(作为单个参数)。有关示例,请参阅this question

【讨论】:

  • 请注意,尽管 varargs 看起来像多个参数,但编译后它只是变成 1 个接受 varargs 类型数组的参数。
  • 实际上,如果我们也考虑 MethodHandles,反射可能很重要,但是与其添加逻辑来处理这种情况,不如将方法句柄转换为不使用可变参数更容易:stackoverflow.com/questions/52093694/…跨度>
【解决方案2】:

一个明显的非答案:反射无关紧要。这两种方法都期望一个 Object 数组作为参数传递。

当在反射中以完全相同的方式使用这两种方法时,源代码是“array”还是“varargs”又有什么关系?!你看,当信息对于你需要做的事情来说不是必需的,那么不关心这些细节是一件好事。

除此之外:显然编译器需要能够区分这两种方法,因此可以在类文件中获得信息。但是对于反思,如前所述,这并不重要。因此,如果您不能使用反射来区分需要数组的方法和需要可变参数的方法,我不会感到惊讶。

【讨论】:

  • 这不是我想要的。我想在调用该方法之前知道接收到的参数是否正常。因此,我需要知道该方法接受多少个参数,使用 Object 时传入 3 个参数是可以的...但对于 Object[] 则不行
  • 这就是我要的。编译器如何知道该方法是用 Object... 而不是 Object[] 定义的
  • @FrancescLordan 错误,不。这不是你要问的。反射与编写编译器相同。编译器必须了解确切的类型。对于反思,重要的两者之间没有区别。当然,另一个答案告诉您如何找到答案,但同样:这并没有改变调用此类方法的代码只关心传递数组的事实!
  • 不,传递 3 个参数是好的。您的代码必须创建一个临时数组并传递 one 参数。
  • 实际上,如果我们也考虑 MethodHandles,反射可能很重要,但是与其添加逻辑来处理这种情况,不如将方法句柄转换为不使用可变参数更容易:stackoverflow.com/questions/52093694/…跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2012-04-16
  • 2020-12-09
  • 2020-06-06
  • 1970-01-01
  • 2016-04-25
相关资源
最近更新 更多