Java unpacking argument lists
Solution 1
public void printStrings(String... strings)
{
// the strings parameter is really a String[].
// You could do anything to it that you normally
// do with an array.
for(String s : strings){
System.out.println(s);
}
}
Can be called like this:
String[] stringArray = new String[10];
for(int i=0; i < stringArray.length; i++){
stringArray[i] = "String number " + (i+1);
}
printStrings(stringArray);
The ...
syntax is really syntactic sugar for arrays.
Java doesn't have the facility that you describe, but you could fake it several ways.
I think the closest approximation means overloading any function that you want to use in that fashion using varargs.
If you have some method:
public void foo(int a, String b, Widget c) { ... }
You can overload it:
public void foo(Object... args) {
foo((Integer)args[0], (String)args[1], (Widget)args[2]);
}
But this is really clumsy and error prone and hard to maintain.
More generically, you could use reflection to call any method using any arguments, but it's got a ton of pitfalls, too. Here's a buggy, incomplete example of how it gets ugly really fast:
public void call(Object targetInstance, String methodName, Object... args) {
Class<?>[] pTypes = new Class<?>[args.length];
for(int i=0; i < args.length; i++) {
pTypes[i] = args[i].getClass();
}
Method targetMethod = targetInstance.getClass()
.getMethod(methodName, pTypes);
targetMethod.invoke(targetInstance, args);
}
Solution 2
If the function you're calling is not a varargs function (declared with ...) then you do need to use reflection. Method.invoke()
takes an array Object[]
of arguments.
The tough part via reflection is finding the right method (well, it's easy if there's only one method with the same name, otherwise it's very difficult).
The cost is the extra time to lookup/invoke the method.
Of course, if you know the specific method at compile-time, then you can deal with this manually, e.g. here for a 3-argument function:
Object[] args = /* get args from somewhere */
callSomeNonVarargsFunction((Cast1)args[0], (Cast1)args[1], (Cast1)args[2]);
Related videos on Youtube
Kevin
Updated on June 01, 2022Comments
-
Kevin almost 2 years
Here's another question of "How would I do this in Java?" In Python, I can use the '*' symbol to unpack arguments like so:
>>> range(3, 6) # normal call with separate arguments [3, 4, 5] >>> args = [3, 6] >>> range(*args) # call with arguments unpacked from a list [3, 4, 5]
Java supports getting a list of args with
...args
syntax, but is there a way (perhaps using the Reflection libraries?) to unpack those for some other function?-
Kaj almost 13 yearsCan you explain what the python code does?
-
Kevin almost 13 years@Kaj Sure. range() is a Python function that takes two integer arguments and produces an array of each integer between them, excluding the upper bound. The
*args
syntax takes the already-defined arrayargs
and expands / unpacks it into two distinct function arguments. It's like callingrange(args[0], args[1])
.
-
-
Oliver Charlesworth almost 13 yearsIndeed, but the OP is interested on whether you can do this for non-variadic methods.
-
Jonathon Faust almost 13 years@Oli what do you mean? It's not clear what he means by "unpack those for some other function."
-
Oliver Charlesworth almost 13 yearsI believe he means "is there a way to programatically access (e.g. iterate over) the parameter values for the current method?"
-
Oliver Charlesworth almost 13 yearsI don't think this is what the OP means. I believe he wants to be able to programatically access the arguments for the current method.
-
Jonathon Faust almost 13 years@Oli hmm...wouldn't that just be by name?
-
Oliver Charlesworth almost 13 yearsIn a generic sense. i.e. some construct that will always give you
args[]
, whereargs[0]
refers to the first argument of the method, etc. -
Admin about 5 yearsThat "the
...
syntax is really syntactic sugar for arrays" isn't really relevant -- the Python*
syntax that OP's drawing a comparison to is also 'really syntactic sugar for tuples.' The meat of the question is just whether it's possible to unpack an iterable in Java