Var-Arg Methods(Variable number of argument methods)
Up until Java 1.4, we could not declare a method with a varying number of arguments. If there is a change in the number of arguments required, a new method should be used with the required number of arguments. This increases the amount of code and reduces readability.
To overcome this problem Var-Arg methods were introduced in Java 1.5. Var-Arg methods allow us to declare a method which can accept a varying number of arguments. A Var-Arg method is declared as follows: m1(int... x). This method can be called by passing any number of int values, also by passing no values.
When a Var-Arg argument is passed into a Var-Arg method, the argument is internally converted into a one dimensional array. Hence within the Var-Arg method, we can differentiate the values using array index.
import java.lang.*;
import java.util.*;
class Test {
public static void main(String[] args) {
sumOfIntegers(); // VALID: var-arg methods can be called with no values
sumOfIntegers(10); // VALID: var-arg methods can be called with any varying number of integers
sumOfIntegers(10,20); // VALID: var-arg methods can be called with any varying number of integers
sumOfIntegers(10,20,30,40,50); // VALID: var-arg methods can be called with any varying number of integers
}
public static void sumOfIntegers(int... args) {
int sumTotal = 0;
for(int i : args) {
sumTotal += args[i];
}
System.out.println("----------------------------------------------------------");
System.out.println("The sumOfIntegers() method was called with " + args.length + " arguments.");
System.out.println("The sum of " + Arrays.toString(args) + " is " sumTotal + ".");
System.out.println("----------------------------------------------------------");
}
}When declaring a Var-Arg method, the syntax of the Var-Arg is important:
import java.lang.*;
import java.util.*;
class Test {
public static void main(String[] args) {
sumOfIntegers(); // VALID: var-arg methods can be called with no values
sumOfIntegers(10); // VALID: var-arg methods can be called with any varying number of integers
sumOfIntegers(10,20); // VALID: var-arg methods can be called with any varying number of integers
sumOfIntegers(10,20,30,40,50); // VALID: var-arg methods can be called with any varying number of integers
}
public static void sumOfIntegers(int... args) {} // VALID: Popular way of declaring a Var-Arg method
public static void sumOfIntegers(int ... args) {} // VALID: The spaces are ignored by the compiler
public static void sumOfIntegers(int ...args) {} // VALID: The spaces are ignore by the compiler
public static void sumOfIntegers(int...args) {} // VALID: Since space is ignored by compiler, it is not necessary to have it
public static void sumOfIntegers(int args...) {} // INVALID: The dots must come before 'args'
public static void sumOfIntegers(int. ..args) {} // INVALID: The dots must be next to each other
public static void sumOfIntegers(int .args..) {} // INVALID: The dots must be next to each other
}Var-Arg methods can take a mix of Var-Arg arguments and normal arguments. However, when mixing Var-Arg arguments and normal arguments, the Var-Arg parameter should always come last.
import java.lang.*;
import java.util.*;
class Test {
public static void main(String[] args) {
sum(OCT, 1, 2);
sum(HEX, 1, 2);
sum(DEC, 1, 2);
sum2(1, 2, 3, DEC);
}
public static void sum(String base, int... args) { // VALID: can use both normal and Var-Arg arguments, as long as Var-Arg argument comes last
switch (base) {
case "OCT":
sumOfOct(args);
break
case "DEC":
sumOfDec(args);
break
default:
unsupportedType(base);
break;
}
}
public static void sum2(int... args, String base) { // INVALID: Var-Arg argument should always come last
switch (base) {
case "OCT":
sumOfOct(args);
break
case "DEC":
sumOfDec(args);
break
default:
unsupportedType(base);
break;
}
}
private void sumOfOct(int... args) {}
private void sumOfDec(int... args) {}
private void unsupportedType(String base) {}
}When using a Var-Arg method, only one Var-Arg argument can be used as parameters, you cannot use multiple Var-Arg arguments in one method.
import java.lang.*;
import java.util.*;
class Test {
public static void m1(int... x, double... d) {} // INVALID: cannot have more that one Var-Arg argument
}Within a class, we cannot have more than one method with the same signature. Each method signature within a class must be unique. It’s important to note that the return type is not considered part of the method signature. So even if the methods have a different return type, they are still considered the same, if they have the same method signature in a class.
import java.lang.*;
import java.util.*;
class Test {
public static void m1(int x) {} // INVALID: cannot have more that one method with the same signature: m1(int)
public static int m1(int x) { return 0; } // INVALID: even though they have different return type, they still have the same signature: m1(int)
}The same rule applies when using Var-Arg methods, since they are internally converted to arrays, you cannot have other methods with the same signature in the same class. If we did this, we would get a compile time error stating "cannot declare both m1(int[]) and m1(int...)"
import java.lang.*;
import java.util.*;
class Test {
public static void m1(int... x) {} // INVALID: cannot have more that one method with the same signature: m1(int[])
public static int m1(int... x) { return 0; } // INVALID: even though it has a different return type, it still have the same signature: m1(int[])
public static void m1(int[] x) { return 0; } // INVALID: even though it is declared using array, it matches signature of Var-Arg methods: m1(int[])
}There are cases where there may be some ambiguity, such as when methods have different signatures, but match in certain cases. Since Var-Arg method can take from 0 arguments to as many as the developer would require, if there is another method in the same class that is named the same as the Var-Arg method and takes the same data type, then you won’t get a compile time error, since their signatures are different. In this case when the methods are called, the Var-Arg method gets the least priority, it is only called if no other method matches the signature. It’s the same as the default case in a switch statement, where default is called if none of the case statements match the condition.
import java.lang.*;
import java.util.*;
class Test {
public static void main(String[] args) {
m1(); // Var-Arg method
m1(1,2); // Var-Arg method
m1(1); // General method
}
public static void m1(int... args) {
System.out.println("Var-Arg method");
}
public static void m1(int arg) {
System.out.println("General method");
}
}Equivalence between Var-Arg argument and one dimensional array
Where a one dimensional array is used as an argument, a Var-Arg argument can also be used in it’s place, because an array can be used as a Var-Arg parameter. An example of this is that you can replace main(String[] args), with main(String... args).
m1(int[] x) | m1(int... x) |
|---|---|
m1(new int[]{10}) | m1(new int[]{10}) |
m1(new int[]{10,20}) | m1(new int[]{10,20}) |
m1(new int[]{10,20,30}) | m1(new int[]{10,20,30}) |
m1(10) | |
m1(10,20) | |
m1(10,20,30) |
While we can replace one dimensional array methods with Var-Arg methods, the opposite is not supported. This is because a one dimensional array method only accepts one dimensional arrays as arguments and will not accept any other values, whereas a Var-Arg methods accepts one dimensional arrays as well as 0 to many arguments. Therefore the one dimensional array method is not as flexible as the Var-Arg method.
Therefore m1(int[] x) can be replaced by m1(int... x), butm1(int... x) cannot be replaced by m1(int[] x)
In memory representation of Var-Arg arguments
| Var-Arg argument | In memory representation |
|---|---|
Passing a group of int values: m1(int.. x) | Represented in memory as a one dimensional array of int values int[] x |
Passing a group of String values: m1(String... x) | Represented in memory as a one dimensional array of String values String[] x |
Passing a group of one dimensional arrays: m1(int[]... x) | Represented in memory as a one dimensional array of arrays i.e. a 2D array int[][] x |
Passing a group of two-dimensional arrays: m1(int[][]... x) | Represented in memory as a one dimensional array of 2D arrays i.e. a 3D array int[][][] x |
import java.lang.*;
import java.util.*;
class Test {
public static void main(String[] args) {
m1(new int[]{10,20,30},new int[]{40,50,60});
}
public static void m1(int[]... args) {
for(int[] val : args) {
System.out.println(val[0]); // prints 10, then 40
}
}
}