• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Passing an array into a vararg method (in Reflection API)

 
Mark Vedder
Ranch Hand
Posts: 624
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I working with the Java 1.5 implementation of Reflection API. I need to reflectively access a private method that takes a String array as a parameter:



I am using the getDeclaredMethod(String name, Class... parameterTypes) method to gain access. I have used this method many time before. However, I am running into a problem since my parameterType is an array. When I attempt the following:



I get a warning during compile time:

1 warning
Warning (55,1) non-varargs call of varargs method with inexact argument type for last parameter;
cast to java.lang.Object for a varargs call
cast to java.lang.Object[] for a non-varargs call and to suppress this warning


and an exception at runtime:

java.lang.IllegalArgumentException: wrong number of arguments
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method


Based on the warnings information, I have attempted to figure out the syntax to resolve this, but since I need a Class and not an Object for my vararg, I am not sure how to go about doing this. My Google searches have not found any suggestions.

Any suggestions or help with a way of doing this would be very much appreciated.
[ October 28, 2006: Message edited by: Mark Vedder ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24208
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't believe it's the call to getDeclaredMethod() that's the problem -- I believe it's the call to invoke(), where the underlying method wants an Object[] (an array of arguments) and you're passing a String[], which is itself an Object[], and it is being misinterpreted as the list of arguments itself, rather than as a single element of that list. You'd get the same error for this code with a pre-Tiger compiler, too. You could cast the String[] to an Object, so it's properly interpreted as one element of a varargs; personally, I'd prefer

method.invoke(instance, new Object[] { args });

because I think it's less obscure (and of course it's what the other version would compile too, anyway.)
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[EFH]: You could cast the String[] to an Object

That doesn't quite work. The problem is that what's needed is similar to an array of arrays. More precisely, it needs to be an array of Objects, one of which (the only one) is a String[]. Simply casting doesn't introduce the extra array level. But this works:

That should be equivalent to the code EFH gave (though we've used the name "args" differently), but neither is equivalent to simply casting the String[] to an Object[].
[ October 28, 2006: Message edited by: Jim Yingst ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24208
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:

That doesn't work


Ah, yes it does, my friend. I didn't say cast to Object[] -- I said cast to Object. If you do that, the compiler doesn't "know" the argument is an array anymore, so it wraps it in a one-element array to pass as the varargs parameter.

You kind of proved my point about that being obscure, though -- if it's not obvious to Jim, then I think it's too obscure to use in normal code!
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, thanks. Oopsie. That's what I get for reading too quickly. I'd been about to post a solution independently, saw you'd just posted, and quickly scanned to see how they related. Too quickly, it seems.
 
Mark Vedder
Ranch Hand
Posts: 624
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Gentlemen,

Thanks so much for you input and successfully solving my issue.

Originally posted by Ernest Friedman-Hill:
I don't believe it's the call to getDeclaredMethod() that's the problem -- I believe it's the call to invoke()...

You are 100% correct of course... and had I paid closer attention to the line number shown in the compile warning and in the stack trace, I would have seen that. I swear that when I did that last night, the line number reported was that of the getDeclaredMethod(). Chalk it up to being too mentally fatigued after a 10-hour coding session I guess. :roll: At least that is my excuse for making such a careless mistake... not that I would necessarily have solved the issue, but at least I would have been looking in the right place as I was trying to cast the getDeclaredMethod()'s vararg to an Object.

I took Jim's suggestion, along with a heavy dose of commenting, to keep the code as non-obscure as possible.

Again, I thank you both for your prompt and detailed replies. I consistently learn many things from each of you, and others here at the ranch, through your many quality posts. Have a happy Halloween!
[ October 29, 2006: Message edited by: Mark Vedder ]
 
supriya riya
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
i am getting same error arguments type mismatch my set method has a String array.
and my value is Object which has a String seprated by ","
Please help.
Thanks
Code is given below for reference.


 
supriya riya
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
"my set method means"

method.invoke calls a setter method with argument as string array
 
Rob Spoor
Sheriff
Pie
Posts: 20493
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Obviously, value is a String, not a String[] or Object[].

By the way, for the above old posts, it's not necessary to create a new one-element Object[]. Explicitly casting the String[] to Object will also work:
This will cause the String[] to be seen as one single argument instead of an array with all arguments.
 
Vinay Jaasti
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use method.invoke(instance, new Object[]{args});
 
Campbell Ritchie
Sheriff
Posts: 48374
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch Vinay Jaasti

That will create a 1‑element Object array whose member is the array args.
 
Vinay Jaasti
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes..

to get rid of Argument Mismatch exception in reflection,

http://yourmitra.wordpress.com/2008/09/26/using-java-reflection-to-invoke-a-method-with-array-parameters/
 
Campbell Ritchie
Sheriff
Posts: 48374
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic