• Post Reply Bookmark Topic Watch Topic
  • New Topic

Understanding Java varargs - why should vararg be the last argument in a method call ?  RSS feed

 
Ranch Hand
Posts: 182
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Varargs should be the last argument in a method call. Why ?
 
Ranch Hand
Posts: 411
5
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To my understanding based on the mechanics of method calls... the compiler places the called method on a stack frame... it calculates the amount of memory needed for the method using its signature and local variable declarations...

If we have a method signature such as:


It knows before hand that it needs to allocate space for two ints on the stack for the method...

As with varargs it cannot perform these calculations because it is not known before hand... therefore its declaration has to be placed as the last argument in order to grow the stack based on the amount of arguments passed in at method invocation...
 
Ranch Hand
Posts: 250
1
Chrome Eclipse IDE
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It actually has the be the last argument. While it wouldn't always have to be the rule, it makes the compiler's job easier. The rule is in place to avoid the problem of a signature like private void foo(String... var1, String var2). Hopefully you see how that would be a problem.
 
Ali Gordon
Ranch Hand
Posts: 182
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Joel Christophel wrote:It actually has the be the last argument. While it wouldn't always have to be the rule, it makes the compiler's job easier. The rule is in place to avoid the problem of a signature like private void foo(String... var1, String var2). Hopefully you see how that would be a problem.


Makes sense. So, a method call like foo(a, b, c) is ambiguous because it seems that all String args a, b and c are passed into "String var1", but no arg is passed into String var2 .
Hence the compiler error - The variable argument type String of the method foo must be the last parameter.

EDIT - As an aside, I wonder why someone would want to have a method with the signature you mentioned. It would be better to put all the strings into one one vararg.

+1 and thank you very much.



 
Ali Gordon
Ranch Hand
Posts: 182
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rico Felix wrote:To my understanding based on the mechanics of method calls... the compiler places the called method on a stack frame... it calculates the amount of memory needed for the method using its signature and local variable declarations...

If we have a method signature such as:


It knows before hand that it needs to allocate space for two ints on the stack for the method...

As with varargs it cannot perform these calculations because it is not known before hand... therefore its declaration has to be placed as the last argument in order to grow the stack based on the amount of arguments passed in at method invocation...


The compiler does not allocate any memory. It checks if your code is correct and if correct, then convert it into object/machine code (bytecode in case your machine is a JVM). Memory allocation is supposed to be done by the JVM.

The JVM won't be confused because of the reason you mentioned, i.e, how much memory to allocate ? Regardless of the order of args, the memory remains variable. The JVM will be actually confused because of the reason Joel Christophel mentioned. So, the compiler prevents that by throwing an error about the order.
 
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, that method call would not be ambiguous.
Agree that it is easier to parse if the varargs parameter is the last parameter. What the compiler does is to convert the varargs to an array, so the length of the array is the number or arguments actually passed minus the number of preceding parameters. Let's have come concrete examples:-Now the compiler will see No 3 and No 5 as ambiguous: they will both turn into foo(int, int, int[]), so it won't compile them. So we delete No 5.You can see that line 3 is an exact match for No 6, and line 5 will only match two ints followed by a 2‑element int[], so it prints No 3. But what about the call on line 4? Will that match
two ints followed by a 1‑element int[] or three ints?

If you try it you will find that the compiler prefers the three ints, so your output includes No 4.
Remember the choice of which overloaded method is called is made at compile‑time. The mechanism is rather complicated but it is in the Java Language Specification. Start here and you will probably find a link there to how such methods are chosen at compile‑time, maybe that marked §15.12.2.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If you meant that method call would be ambiguous to foo(String... words, String s), yes, that would be ambiguous.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you know you can inspect the bytecode? You create a class with a varargs method, then you print its bytecode with javap -c Foo. That will allow you to see varargs being converted to an array.
Remember a varargs call has to be visible to the compiler. You can write f.foo(123, 234, 345, 456, 567), but you cannot write a variable number of varargs. If you want a variable number of arguments at runtime you can only pass an array, so you have to declare the method with a parameter specifically of array type with [] not ...
 
Ali Gordon
Ranch Hand
Posts: 182
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:If you meant that method call would be ambiguous to foo(String... words, String s), yes, that would be ambiguous.


Thanks campbell. That is what I meant.
 
Rico Felix
Ranch Hand
Posts: 411
5
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have no idea why I would say that the compiler allocates memory ... sometimes my thoughts are disorganized
 
Ali Gordon
Ranch Hand
Posts: 182
Eclipse IDE Hibernate Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rico Felix wrote:Have no idea why I would say that the compiler allocates memory ... sometimes my thoughts are disorganized


No worries. It happens to everyone.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!