Varargs in Java: Variable Arguments Explained With Examples

Difficulty: Beginner–Intermediate · Importance: Medium · Java version: Java 5+ (@SafeVarargs: Java 7+) · Last updated: 1 Nov 2026

Think about it: System.out.printf("%s", name) takes 2 arguments. printf("%s scored %d out of %d", name, marks, total) takes 4. There’s only one printf method that accepts any number of values. How? With varargs.

Quick Answer

Varargs in Java (variable arguments, Java 5+) let a method accept zero or more arguments of the same type, declared with three dots: int... numbers. The compiler packs the arguments into an array, so inside the method you use it exactly like an int[]. A method can have only one varargs parameter, and it must be the last parameter.

Before you start: varargs build on Method Parameters and interact with Method Overloading.

The Problem Varargs Solve

Suppose you need a sum method that works for 2, 3, 4… numbers. Before Java 5 you had two clumsy options:

  1. Overload for each count: sum(int a, int b), sum(int a, int b, int c), and so on, forever.
  2. Take an array, and make every caller build one:

Output:

 60

Calling it the natural way, sum(10, 20, 30), fails:

ArrayParamCall.java:5: error: method sum in class ArrayParamCall cannot be applied to given types;        System.out.println(sum(10, 20, 30));
^
required: int[]
found: int,int,int
reason: actual and formal argument lists differ in length

Varargs give you the natural call and a single method.

Syntax of Varargs in Java


Output:

The ... (ellipsis) is written straight after the type. int... numbers, int ...numbers and int ... numbers all compile, but int... numbers is the standard style.

How Do Varargs Work Internally?

The varargs parameter is an array. Inside the method, numbers is a normal int[], with .length, indexing and loops.

Whiteboard
Loading diagram...

The compiler, not the JVM, rewrites each call: it builds an array from your arguments (an empty one when there are none) and passes that single array to the method.

The bytecode proves it. javap -v SumDemo (JDK 25):

   static int sum(int...);    descriptor: ([I)I
flags: (0x0088) ACC_STATIC, ACC_VARARGS

The descriptor ([I)I means “takes an int[], returns an int”. The ACC_VARARGS flag only tells the compiler it may accept separate arguments. And javap -c shows the call sites building arrays:

          3: iconst_0         4: newarray       int          // sum()     → new int[0]
6: invokestatic #13 // Method sum:([I)I
...
15: iconst_1
16: newarray int // sum(5) → new int[1], then stores 5
...
21: iastore
22: invokestatic #13 // Method sum:([I)I

Two practical consequences:

1. Zero Arguments Give an Empty Array, Not null

Output:

length = 3, contents = [Delhi, Pune, Kochi], is null? false  first = Delhi
length = 0, contents = [], is null? false
length = 2, contents = [Mumbai, Chennai], is null? false
first = Mumbai

▶ Try it in the ExamAdda Compiler

2. You Can Pass an Existing Array

As inspect(metros) shows, a varargs method accepts an array directly. That array is not copied, so changes inside the method are visible to the caller (pass by value of the reference). When you pass separate values, a new array is built for the call:

Output:

[40, 55, 77]35, 50

More on why: Pass by Value in Java. Arrays in depth: Introduction to Arrays.

Mixing Fixed Parameters With Varargs

Fixed parameters come first; the varargs parameter collects everything left over.

Output:

Asha: 3 item(s), total Rs 465.5Ravi: 1 item(s), total Rs 999.0
Meena: 0 item(s), total Rs 0.0

Requiring At Least One Argument

max() with no values makes no sense. Make the first value a normal parameter so the compiler enforces “at least one”:

Output:

745

Calling max() now fails at compile time (required: int,int[], found: no arguments) instead of crashing at runtime on rest[0].

Rules of Varargs in Java

  1. Declare it with Type... name; all the values must be of that type (or convertible to it).
  2. Only one varargs parameter per method.
  3. It must be the last parameter.
  4. Inside the method it’s an array of that type; zero arguments give an empty array.
  5. You can pass an existing array of that type instead of separate values.
  6. m(int... a) and m(int[] a) have the same signature, so they can’t both exist.
  7. During overload resolution, varargs methods are considered last (phase 3).

Can a Method Have Two Varargs Parameters?

No. The compiler couldn’t know where the first list ends:

 TwoVarargs.java:2: error: varargs parameter must be the last parameter    static void record(int... marks, String... names) { }
^
1 error

The same error appears when a single varargs parameter isn’t last (record(int... marks, String name)). Some tutorials show the message “Multiple vararg-parameters are prohibited”; that’s an IDE message, not the javac error above.

Varargs and Method Overloading

Fixed-Arity Overloads Win

Varargs methods are tried only after every exact, widening and boxing option fails:

Output:

fixed: Hello Ashavarargs: Hello to 2 people
varargs: Hello to 0 people

▶ Try it in the ExamAdda Compiler

This is phase 3 of the resolution rules from Method Overloading.

Ambiguous Varargs Overloads

Zero arguments with two varargs overloads:

 AmbiguousZero.java:8: error: reference to log is ambiguous        log();          // which one?
^
both method log(int...) in AmbiguousZero and method log(String...) in AmbiguousZero match

Overlapping varargs signatures:

 AmbiguousTwo.java:6: error: reference to add is ambiguous        add(1, 2);
^
both method add(int...) in AmbiguousTwo and method add(int,int...) in AmbiguousTwo match

Fix: avoid overloading varargs methods with each other. Give them different names (logCodes, logMessages) or keep just one.

Passing null to a Varargs Method

null has two possible meanings: “an array that is null” or “one element that is null”. Casting picks one:

Output:

length = 1, first = nullarray itself is null
array itself is null

A bare count(null) compiles, but javac -Xlint warns:

 NullVarargs.java:13: warning: non-varargs call of varargs method with inexact argument type for last parameter;        count(null);                // treated as (String[]) null, with a warning
^
cast to String for a varargs call
cast to String[] for a non-varargs call and to suppress this warning

Without the words == null guard, words.length would throw NullPointerException. Always cast null explicitly when calling a varargs method.

Varargs vs Array Parameter

int... nums (varargs)int[] nums (array)
Call with separate values f(1, 2, 3)✅❌ compile error
Call with an array f(arr)✅✅
Call with no arguments f()✅ (empty array)❌
Type inside the methodint[]int[]
Position in the parameter listMust be last, only oneAnywhere, any number
Can both exist with the same name?No: “cannot declare both show(int...) and show(int[])”

Varargs in the Java Library

Output:

Asha scored 87 out of 100GST   | 18.0
Home > Java > Methods > Varargs
[Mon, Tue, Wed]
[3, 1, 2]

printf(String format, Object... args), String.format, String.join and Arrays.asList are all varargs methods.

Interesting internals fact: List.of (Java 9+) isn’t only varargs. javap java.util.List on JDK 25 shows twelve overloads: of(), of(E), of(E, E) … up to ten elements, plus of(E...). The fixed versions avoid creating a varargs array for the most common small calls. That’s a real example of a library trading extra overloads for performance.

Can the main Method Use Varargs?

Yes. String... args and String[] args are the same signature, so this is a valid entry point:

Output (run as java MainVarargs Pune 2026):

 Arguments received: 2  Pune
2026

Generic Varargs and @SafeVarargs (Preview of Generics)

When the varargs type is a generic type such as T..., javac -Xlint warns:

text
GenericVarargs.java:5: warning: [unchecked] Possible heap pollution from parameterized vararg type T
    static <T> List<T> listOf(T... items) {
                                   ^

Because generic types are erased at runtime, the compiler can’t guarantee the array’s real type. If your method only reads the elements (it never stores into or exposes the array), you can mark it @SafeVarargs (Java 7+, allowed on static, final and, since Java 9, private methods). This is library-author territory; you’ll meet it again in the Generics section (Introduction to Generics).

Real-World Example: Class Average Report

Output:

Maths: 4 students, average 80.75, highest 92Physics: 2 students, average 63.00, highest 71
Chemistry: no marks entered
English: 3 students, average 81.67, highest 90

▶ Try it in the ExamAdda Compiler

The method handles separate values, no values (guarded by the marks.length == 0 check, which prevents dividing by zero and reading marks[0] from an empty array), and an existing array, all through one signature. printf itself is a varargs call.

Common Mistakes With Varargs

Mistake 1: Varargs Not Last (or Two Varargs)

 NotLast.java:2: error: varargs parameter must be the last parameter    static void record(int... marks, String name) { }
^

Mistake 2: Declaring Both an Array and a Varargs Version

 BothArrayAndVarargs.java:3: error: cannot declare both show(int...) and show(int[]) in BothArrayAndVarargs    static void show(int... values) { }
^

Why: both compile to show(int[]).

Mistake 3: Reading the First Element Without Checking the Length


Mistake 4: Overloading Varargs With Varargs

log(int...) with log(String...), or add(int...) with add(int, int...), gives “reference to … is ambiguous” (real messages above). Use distinct names.

Mistake 5: Passing a Bare null

count(null) passes a null array, which causes a NullPointerException on .length unless you guard it. Cast explicitly: (String) null for one null element, or (String[]) null for a null array.

Mistake 6: Using Varargs in a Hot Loop

Each call with separate values allocates a new array. That’s fine almost everywhere, but in a method called millions of times, add fixed-arity overloads for the common cases, as List.of does.

Best Practices

  1. Use varargs when callers naturally pass a short, variable list of the same type: sum(…), log(…), printf(…).
  2. Put required values in fixed parameters (max(int first, int... rest)).
  3. Treat the varargs array as read-only unless modifying the caller’s array is the point.
  4. Don’t overload varargs methods with other varargs methods.
  5. Always handle the empty case.
  6. Prefer a List parameter when callers usually already have a collection.
  7. Use @SafeVarargs only on generic varargs methods that truly don’t store into the array.

Interview Questions on Varargs

How to answer in an interview: “What are varargs in Java?”
“Varargs, added in Java 5, let a method accept zero or more arguments of one type using Type.... The compiler packs the arguments into an array, so inside the method the parameter is a normal array. A method can have only one varargs parameter, and it must be last. In overloading, varargs methods are chosen only after exact, widening and boxing matches fail.”

Output-Prediction Questions

Q1. static void f(int... a) { System.out.println(a.length); } called as f();
Answer: 0. It’s an empty array, not null.

Q2. Overloads g(int a, int b) and g(int... a); call g(1, 2).
Answer: g(int, int). Fixed-arity methods win before varargs is considered.

Q3.

Answer: 1. It’s an array with one null element.

Conceptual Follow-Ups

  1. Can a method have two varargs? No: “varargs parameter must be the last parameter”.
  2. Are f(int... a) and f(int[] a) different overloads? No. They’re the same signature, and declaring both is an error.
  3. What is a inside f(int... a)? An int[].
  4. Can main be main(String... args)? Yes.
  5. Why does List.of have overloads for up to 10 elements? To avoid allocating a varargs array for common small calls.

More: Java Interview Questions for Freshers · Intermediate Questions

Practice Exercises

  1. Easy: Write static double average(double... values) that returns 0 for no values.
  2. Easy: Write static void printAll(String title, String... lines) that prints a title and numbered lines.
  3. Easy–Medium: Write static int min(int first, int... rest) and explain why min() won’t compile.
  4. Medium: Write static boolean containsAll(String text, String... words) that checks whether every word appears in text.
  5. Medium: Create overloads show(int, int) and show(int...), predict the output for show(1), show(1, 2) and show(1, 2, 3), then run them.

Practise on ExamAdda Practice and test in the ExamAdda Compiler.

FAQs

1. What are varargs in Java?
Varargs (variable-length arguments, Java 5+) let a method accept zero or more values of the same type, declared as Type... name. Inside the method the parameter is an array.

2. Can a method have more than one varargs parameter?
No. Only one varargs parameter is allowed, and it must be the last parameter. Otherwise javac reports “varargs parameter must be the last parameter”.

3. What happens if I call a varargs method with no arguments?
The method receives an empty array (length 0), not null.

4. What is the difference between varargs and an array parameter?
Both are arrays inside the method, but a varargs method can be called with separate values or none at all, while an array parameter requires the caller to pass an array.

5. Can the main method use varargs?
Yes. public static void main(String... args) is equivalent to main(String[] args) and works as the entry point.

6. Why is calling a varargs method ambiguous sometimes?
When two overloads both accept the call through varargs (for example log(int...) and log(String...) called with no arguments), neither is more specific, so the compiler reports “reference to … is ambiguous”.

7. What is @SafeVarargs?
An annotation (Java 7+) that suppresses heap-pollution warnings on generic varargs methods. Use it only when the method doesn’t store into or expose the varargs array.

Article Summary

  • Varargs (Type..., Java 5+) let a method take zero or more same-type arguments; the compiler packs them into an array.
  • Inside the method the parameter is an array; no arguments mean an empty array, and you may pass an existing array.
  • Only one varargs parameter is allowed, and it must be last; f(int...) and f(int[]) clash.
  • In overloading, varargs methods are chosen last, and varargs-vs-varargs overloads easily become ambiguous.
  • Cast null explicitly, handle the empty case, and remember that each call may allocate an array.

Next → Recursion in Java · ← Previous: Method Overloading

References: Oracle Java Tutorials: Arbitrary Number of Arguments · JLS §8.4.1: Formal Parameters (variable arity) · Javadoc: SafeVarargs