Definition
Varargs (String...) and arrays (String[]) are interchangeable in this context:
- Internally identical. The compiler converts
String...toString[]in the bytecode. The JVM sees the same signature. - Valid entry point.
public static void main(String... args)works as the program's main method. - Convention. Most codebases and the JLS examples use
String[] args. UseString...only if you have a specific reason.
Two ways to write the same bank form. The form accepts a list of account numbers either as a pre-filled array or as a blank section where you write each number separately (varargs). The processing clerk sees the same data either way.
Understanding the Concepts
Does String... args work as main?
Yes. The compiler treats String... (varargs) and String[] (array) as identical in the bytecode. The JVM looks for a method with the signature main(String[]), and since varargs compiles to exactly that, it matches.
package com.bank;
public class VarargsMain {
public static void main(String... args) { // varargs syntax
System.out.println("Args count: " + args.length);
for (String arg : args) {
System.out.println(" " + arg);
}
}
}
java com.bank.VarargsMain SAV2001 CUR3001 50000
# Output:
# Args count: 3
# SAV2001
# CUR3001
# 50000
It works exactly like String[] args.
Why are they the same?
Varargs is syntactic sugar. The compiler converts String... to String[] in the bytecode. You can verify this with javap.
// These two signatures produce identical bytecode
public static void main(String[] args) { }
public static void main(String... args) { }
# Verify with javap:
javap -c VarargsMain
# Output: public static void main(java.lang.String[]);
# The bytecode signature is String[] regardless of which syntax you used
What is the difference between varargs and array in general?
Outside of main, varargs allows calling with individual arguments without creating an explicit array. This is the real benefit of varargs.
package com.bank.util;
import java.math.BigDecimal;
public class FeeCalculator {
public static BigDecimal totalFees(BigDecimal... fees) {
BigDecimal total = BigDecimal.ZERO;
for (BigDecimal fee : fees) {
total = total.add(fee);
}
return total;
}
}
// Varargs call: pass individual values
FeeCalculator.totalFees(
new BigDecimal("100"),
new BigDecimal("200"),
new BigDecimal("50")
); // returns 350
// Zero args
FeeCalculator.totalFees(); // returns 0
// Array call: also works
BigDecimal[] feeArray = { new BigDecimal("100"), new BigDecimal("200") };
FeeCalculator.totalFees(feeArray); // returns 300
With a BigDecimal[] parameter, only the array call would compile. Varargs allows both.
What are the varargs rules?
Varargs has three constraints that you must know for interviews.
// Rule 1: Varargs must be the LAST parameter
public void process(String accountId, BigDecimal... amounts) { } // OK
// public void process(BigDecimal... amounts, String accountId) { } // ERROR
// Rule 2: Only ONE varargs parameter allowed
// public void process(int... a, String... b) { } // ERROR
// Rule 3: Varargs can receive zero arguments
process("SAV2001"); // amounts is an empty array, not null
What about varargs with overloading?
Varargs can cause ambiguity when combined with method overloading. The compiler picks the most specific match, but this can be confusing.
package com.bank.service;
public class TransferService {
public void log(String message) {
System.out.println("Specific: " + message);
}
public void log(String... messages) {
System.out.println("Varargs: " + messages.length);
}
}
TransferService svc = new TransferService();
svc.log("transfer complete"); // calls log(String) – more specific
svc.log("a", "b"); // calls log(String...) – only match
svc.log(); // calls log(String...) – zero args
The compiler always prefers a non-varargs overload when one matches. This is an interview edge case.
Should you use String... in main?
No, by convention. Use String[] args because:
- It is the universal standard that every Java developer recognizes.
- It matches the JLS and official documentation.
- It avoids questions from code reviewers about whether it was intentional.
What should a senior engineer know?
- Varargs creates a new array on each call. For hot paths, this allocation can matter. But for main, it does not.
- @SafeVarargs suppresses heap pollution warnings for generic varargs:
@SafeVarargs public static.List listOf(T... items) { return Arrays.asList(items); } - In banking at National Bank of India, Rajesh uses varargs for utility methods like
AccountValidator.validateAll(Account... accounts)but always usesString[] argsfor main to follow the standard convention.
Visual Overview
public static void main(String[] args) ← standard convention
public static void main(String... args) ← also valid, same bytecode
Compiler converts String... to String[] internally:
Source: main(String... args)
Bytecode: main(java.lang.String[])
→ JVM sees identical signature → accepts as entry point
Varargs vs Array (outside main):
sum(10, 20, 30) ← varargs call (individual values)
sum(new int[]{10,20,30}) ← array call
Both work with int... parameter; only array works with int[]
Key Takeaway
Yes, String... args works as the main method parameter because the compiler converts varargs to an array in the bytecode. The JVM sees String[] either way and accepts it as a valid entry point.
But use String[] args by convention. It is the universal standard, matches the JLS, and avoids confusion in code reviews. The varargs form works, but offers no practical benefit for main.
One sentence to remember: String... and String[] produce identical bytecode, so both work for main – but convention says use String[] args.
---