00:00

Varargs in Java – Methods with Variable Arguments

Last updated: 5 min read

Varargs (variable-length arguments), introduced in Java 5, let a method accept zero or more arguments of the same type. You declare the last parameter with three dots, as in int... numbers, and callers can pass any number of values without building an array themselves. Inside the method, the parameter is an ordinary array.

This tutorial covers the syntax, rules, JDK examples, how varargs interact with overloading, common pitfalls, and @SafeVarargs for generic varargs.

1. Syntax and a First Example

Syntax
returnType methodName(Type... name) { ... }          // name is a Type[] inside
returnType methodName(A a, B b, Type... name) { ... } // varargs must come last
VarargsBasics.java
public class VarargsBasics {
    // 'int... numbers' accepts zero or more ints; inside the method it is an int[]
    static int sum(int... numbers) {
        int total = 0;
        for (int n : numbers) total += n;
        return total;
    }

    public static void main(String[] args) {
        System.out.println("sum()              = " + sum());
        System.out.println("sum(5)             = " + sum(5));
        System.out.println("sum(1, 2, 3, 4)    = " + sum(1, 2, 3, 4));
        System.out.println("sum(new int[]{..}) = " + sum(new int[] {10, 20}));   // an array works too
    }
}
Output
sum()              = 0
sum(5)             = 5
sum(1, 2, 3, 4)    = 10
sum(new int[]{..}) = 30

The compiler converts sum(1, 2, 3, 4) into sum(new int[] {1, 2, 3, 4}). That is why an explicit array is also accepted, and why calling with no arguments gives an empty (not null) array.

2. Varargs with Other Parameters

VarargsWithOtherParams.java
public class VarargsWithOtherParams {
    // Regular parameters first; the varargs parameter must be last (and only one is allowed)
    static String tag(String label, String... values) {
        return label + values.length + " -> " + String.join(" | ", values);
    }

    static void log(String level, String format, Object... args) {
        System.out.println("[" + level + "] " + String.format(format, args));
    }

    public static void main(String[] args) {
        System.out.println(tag("languages: ", "Java", "Kotlin", "Scala"));
        System.out.println(tag("empty: "));
        log("INFO", "User %s logged in from %s", "asha", "Pune");
        log("WARN", "Disk usage at %d%%", 91);
    }
}
Output
languages: 3 -> Java | Kotlin | Scala
empty: 0 -> 
[INFO] User asha logged in from Pune
[WARN] Disk usage at 91%

3. Rules

  • A method can have only one varargs parameter.
  • It must be the last parameter.
  • Inside the method it is an array: use .length, indexes and loops.
  • Callers may pass zero or more values, or an array of the right type.
  • main can be declared as public static void main(String... args).

4. Varargs in the JDK

JdkVarargs.java
import java.nio.file.Path;
import java.util.*;

public class JdkVarargs {
    public static void main(String[] args) {
        List<String> list = List.of("a", "b", "c");                 // List.of(E... elements)
        List<Integer> nums = Arrays.asList(3, 1, 2);                // Arrays.asList(T... a)
        System.out.println(list + " " + nums);
        System.out.println(String.format("%s has %d items", "cart", 3));   // format(String, Object...)
        System.out.println(String.join("-", "2026", "10", "11"));   // join(CharSequence, CharSequence...)
        System.out.println(Path.of("home", "asha", "notes.txt"));   // Path.of(String, String...)
        System.out.printf("printf is varargs too: %.2f%n", Math.PI);
    }
}
Output
[a, b, c] [3, 1, 2]
cart has 3 items
2026-10-11
home/asha/notes.txt
printf is varargs too: 3.14

Other examples include EnumSet.of, Stream.of, Collections.addAll and Objects.hash.

5. Overloading and Pitfalls

VarargsPitfalls.java
import java.util.Arrays;
import java.util.List;

public class VarargsPitfalls {
    static void show(Object... items) { System.out.println(items.length + " argument(s): " + Arrays.deepToString(items)); }

    static void pick(int a, int b)  { System.out.println("pick(int, int)"); }
    static void pick(int... values) { System.out.println("pick(int...)"); }

    @SafeVarargs                                          // promises the method does not misuse the generic array
    static <T> List<T> listOf(T... items) { return List.of(items); }

    public static void main(String[] args) {
        show("x", "y");                       // 2 arguments
        show((Object) null);                  // 1 argument: a null element
        show((Object[]) new String[] {"p", "q"}); // an array is passed AS the varargs array: 2 arguments
        show((Object) new String[] {"p", "q"}); // cast: passed as ONE argument

        pick(1, 2);                           // fixed-arity overload wins
        pick(1, 2, 3);                        // only varargs fits

        System.out.println(listOf("red", "green"));
    }
}
Output
2 argument(s): [x, y]
1 argument(s): [null]
2 argument(s): [p, q]
1 argument(s): [[p, q]]
pick(int, int)
pick(int...)
[red, green]
  • Overloading: varargs methods are chosen last. A fixed-arity overload that fits always wins (see Method Overloading).
  • Arrays: passing an array to Object... spreads it into separate arguments; cast to Object to pass the array as a single argument.
  • null: show(null) passes a null array (and the compiler warns); show((Object) null) passes one null element.
  • Ambiguity: overloads like m(int...) and m(Integer...) make m() ambiguous.
  • Performance: each call allocates an array. For hot paths, APIs such as List.of provide fixed-arity overloads for small counts.

6. Generic Varargs and @SafeVarargs

A generic varargs parameter (T... items) creates an array of a non-reifiable type, which can lead to heap pollution, so the compiler warns. If the method only reads the elements and never stores or exposes the array unsafely, annotate it with @SafeVarargs to suppress warnings at every call site. It is allowed on static methods, final instance methods, private methods and constructors.

7. Summary

  • Varargs (Type... name) accept zero or more arguments and are arrays inside the method.
  • Only one varargs parameter is allowed, and it must be last.
  • Fixed-arity overloads are preferred over varargs during overload resolution.
  • Watch out for arrays and null passed to Object....
  • Use @SafeVarargs for safe generic varargs methods.

Related Tutorials