Java Varargs

What is varargs in Java?

Let’s suppose you are creating a Java method. However, you are not sure how many arguments your method is going to accept. To address this problem, Java 1.5 introduced varargs.

Varargs is a short name for variable arguments. In Java, an argument of a method can accept arbitrary number of values. This argument that can accept variable number of values is called varargs.


The syntax for implementing varargs is as follows:

accessModifier methodName(datatype… arg) {
    // method body
}

In order to define vararg, ... (three dots) is used in the formal parameter of a method.

A method that takes variable number of arguments is called a variable-arity method, or simply a varargs method.


First, let’s look at the example without using varargs:

class NoVararg {

    public int sumNumber(int a, int b){
        return a+b;
    }

    public int sumNumber(int a, int b, int c){
        return a+b+c;
    }

    public static void main( String[] args ) {
        NoVararg obj = new NoVararg();
        System.out.println(obj.sumNumber(1, 2));
        System.out.println(obj.sumNumber(1, 2, 3));
    }
}

When you run this program, the output will be:

3
6

As you can clearly see, you had to overload sumNumber() method to make it work for 3 arguments.

What if the user wants to add 5 numbers or 10 or 100?

This can be handled in a neat way with the use of varargs. Let’s see a code example:


Example: Working of varargs

class VarargExample {

    public int sumNumber(int ... args){
        System.out.println("argument length: " + args.length);
        int sum = 0;
        for(int x: args){
            sum += x;
        }
        return sum;
    }

    public static void main( String[] args ) {
        VarargExample ex = new VarargExample();

        int sum2 = ex.sumNumber(2, 4);
        System.out.println("sum2 = " + sum2);

        int sum3 = ex.sumNumber(1, 3, 5);
        System.out.println("sum3 = " + sum3);

        int sum4 = ex.sumNumber(1, 3, 5, 7);
        System.out.println("sum4 = " + sum4);
    }
}

Output:

argument length: 2
sum2 = 6
argument length: 3
sum3 = 9
argument length: 4
sum4 = 16

Here, the sumNumber() method returns the sum of int parameters passed to it (doesn't matter the number of arguments passed).


Note: As you can see, varargs can be really useful in some situations. However, if you are certain about the number of arguments passed to a method, use method overloading instead. For example, if you are certain that sumNumber() method will be used only to calculate the sum of either 2 or 3 arguments, use overloading like in the first example.


Let's take another example. The format() method defined in Java library accepts varargs. In JDK, the format() method is defined as follows:

public static String format(Locale l, String format, Object... args) {
    // body
}

Example: format() Method

class Company {
  public static void main(String[] args) {
    String siteName = "codemy.com";
    int empCount = 6;
    String type = "tutorial website";
    System.out.println(
        String.format(
          "Site Name : %s, Emp Count: %d Type: %s",
            siteName, empCount, type
          )
        );
  }
}

Output:

Site Name : codemy.com, Emp Count: 6 Type: tutorial website

How varargs works behind the scene?

Let’s consider the following pseudo code:

public int sumNumber(int ... nums) {
    // method body
}

The ... syntax tells the Java compiler that the method can be called with zero or more arguments. As a result, nums variable is implicitly declared as an array of type int[ ]. Thus, inside the method, nums variable is accessed using the array syntax.

In case of no arguments, the length of nums is 0.


Overloading Varargs Methods

Similar to typical methods, you can overload a vararg methods. For example,

Before you learn about overloading vararg methods, make sure to learn about Java Method Overloading first.

class VarargOverload {

    private void test(int ... args){
        int sum = 0;
        for (int i: args) {
            sum += i;
        }
        System.out.println("sum = " + sum);
    }

    private void test(boolean p, String ... args){
        boolean negate = !p;
        System.out.println("negate = " + negate);
        System.out.println("args.length = "+ args.length);
    }

    public static void main( String[] args ) {
        VarargOverload obj = new VarargOverload();
        obj.test(1, 2, 3);
        obj.test(true, "hello", "world");
    }
}

Output:

sum = 6
negate = false
args.length = 2

In the above program, test() method is overloaded by changing the number of arguments it accepts.


Things to remember while using Varargs

Here are a couple of things you should remember while working with Java vargars:

1. While defining method signature, always keep varargs at last.

The variable argument must be the last argument passed to the method. Let's consider, you invoked doSomething() method like this:

doSomething(1, 2, 3, 4);

And, your doSomething() method is defined as:

// incorrect method declaration

public void doSomething(int ... nums, int p){
    // method body
}

In this case, compiler cannot figure out the number of arguments passed to nums.

However, if you define your method as:

public void doSomething(int p, int ... nums) {
    // method body
}

The Java compiler assigns the first argument to p, and the remaining int arguments are assigned to nums.

2. A method can have only one varargs parameter.

For example, this method declaration is incorrect:

int doSomething(int p, float ... floatNums, double ... doubleNums) {
    // code
}

Ambiguity in Varargs Method overloading

Let’s consider you overloaded test() method like this:

class Demo { 
  
  static void test(int ... vargs) {
    // method body
  }
    
  static void test(int n, int ... vargs) {
    // method body
  }
}

In the above program, the compiler gets confused if you try to invoke the test() method even though test() methods are overloaded and accepts different number of arguments.

The compiler doesn’t know which method to call. The compiler may think, you are trying to call test(int ... vargs) with one varargs argument. Also, the compiler may think, you are trying to call test(int n, int ... vargs) with argument passed to the first parameter with empty second parameter.

Since there are two possibilities, it causes ambiguity. Because of this, sometimes you may need to use two different method names instead of overloading the varargs method.