4

Is there any way to distinguish these two methods when using reflection to invoke it?

public void method(Object[] args) {}

public void method(Object... args) {}
Francesc Lordan
  • 519
  • 4
  • 24
  • 3
    Your question is a moot point because this code won't even compile. It fails with the error message `error: cannot declare both method(Object...) and method(Object[])`. [See this demo](https://rextester.com/CLDR26037). – Tim Biegeleisen Jul 09 '19 at 05:28
  • 1
    Obviously this code does not compile. The question is how can I distinguish if the method has been declared in one way or the other – Francesc Lordan Jul 09 '19 at 05:44
  • Based on the inability to compile, I'ma assuming that both signatures would appear the same at run time, i.e. `Object[]`. But, why do you need to know the difference? – Tim Biegeleisen Jul 09 '19 at 05:45
  • 1
    Because I receive an array of Objects and I want to know before invoking the method that I can call it with the received parameters. If i have an Object[] parameter, I can only have 1 parameter; otherwise, i can have 3 or even 0 parameters. – Francesc Lordan Jul 09 '19 at 05:57
  • No, you can't. That is what people try to tell you again and again. There are no varargs at runtime. If you intend to call a varargs method using reflection, you have to pass an array! – GhostCat Jul 09 '19 at 07:41

2 Answers2

2

You can test if a Parameter is a varargs parameter via Parameter#isVarArgs().

Returns true if this parameter represents a variable argument list; returns false otherwise.


The Executable interface has a similar method, which both Constructor and Method implement.

Returns true if this executable was declared to take a variable number of arguments; returns false otherwise.


However, if I correctly understand why you're asking this question, knowing this information won't help you. Whether or not the parameter is varargs doesn't affect how you would call Method#invoke. As mentioned by GhostCat and hinted at by Ferrybig, you'll need to pass an array (as a single argument) either way. See this question for some examples.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • 1
    Note that even though varargs look like multiple parameters, after compiling it just becomes 1 parameter that accepts an array of the varargs type. – Ferrybig Jul 09 '19 at 06:55
  • 1
    Actually it can matter for reflections if we will think about MethodHandles too, but then instead of adding logic to handle such case it is easier to just transform method handle to not use varargs: https://stackoverflow.com/questions/52093694/how-to-invoke-a-methodhandle-with-varargs/52101338 – GotoFinal Jul 09 '19 at 17:01
1

A distinct non answer: it doesn't matter for reflection. Both methods expect an array of Object to be passed as argument.

When both methods are used the exact same way in reflection, why would it matter if the source code said "array" or "varargs"?! You see, when information isn't necessary for what you need to do, then it is a good thing to not care about that detail.

Beyond that: obviously a compiler needs to be able to distinguish the two methods, so the information is available in the class file. But for reflection, as said, it does not matter. Therefore it would not surprise me if you can't use reflection to distinguish between a method expecting an array and one expecting a vararg.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • That's not what I'm asking for. I want to know before invoking if the method if the received parameters are ok. Thus, I need to know how many parameters the method accepts, passing in 3 parameters is ok when using Object... but not for Object[] – Francesc Lordan Jul 09 '19 at 05:53
  • That's what I'm asking for. How the compiler knows that the method is defined with Object... and not Object[] – Francesc Lordan Jul 09 '19 at 05:55
  • @FrancescLordan err, no. That is **not** what you were asking. Reflection is **not** the same as writing a compiler. The compiler has to understand the exact type. For reflection, there is no difference between the two that matters. Sure, the other answer tells how you can find out, but again: that doesn't change the fact that the code to invoke such a method only cares about passing an array! – GhostCat Jul 09 '19 at 07:37
  • 1
    And no, passing 3 arguments is **not** okay. Your code has to create a temp array and pass **one** parameter. – GhostCat Jul 09 '19 at 07:39
  • Actually it can matter for reflections if we will think about MethodHandles too, but then instead of adding logic to handle such case it is easier to just transform method handle to not use varargs: https://stackoverflow.com/questions/52093694/how-to-invoke-a-methodhandle-with-varargs/52101338 – GotoFinal Jul 09 '19 at 17:02