Skip to content
  • Varargs & Method Overloading · Java

Varargs & Method Overloading

LearnViaNotes @learnvianotes· 3 min read

Overloading = same name, different parameter lists, chosen at compile time. Varargs (T...) lets a method accept zero or more arguments as an array.

Overloading

Java
public class Main {
    static int area(int side) { return side * side; }
    static int area(int w, int h) { return w * h; }
    static double area(double r) { return Math.PI * r * r; }

    public static void main(String[] args) {
        System.out.println(area(3));
        System.out.println(area(2, 5));
        System.out.printf("%.2f%n", area(1.0));
    }
}
Output
9
10
3.14

Overloads must differ in the number, types or order of parameters. Different return types, parameter names, or exceptions alone are not enough.

Varargs

Java
import java.util.Arrays;

public class Main {
    static int sum(int... nums) {                   // nums is an int[]
        int total = 0;
        for (int n : nums) total += n;
        return total;
    }

    static String tag(String name, Object... attrs) {   // varargs must be LAST
        return name + Arrays.toString(attrs);
    }

    public static void main(String[] args) {
        System.out.println(sum() + " " + sum(1) + " " + sum(1, 2, 3));
        System.out.println(sum(new int[]{4, 5}));       // can pass an array directly
        System.out.println(tag("div", "id", 7, true));
        System.out.println(String.format("%s-%s", "a", "b"));   // printf/format use varargs
    }
}
Output
0 1 6
9
div[id, 7, true]
a-b
  • Only one varargs parameter per method, and it must be the last one.

  • Inside the method it is an ordinary array (possibly empty, never null unless the caller passes null).

  • Each call allocates a new array — hot paths often add fixed-arity overloads (like List.of(e1, e2, …)).

Overload resolution: which method wins?

  1. Phase 1 — exact / widening

    Match without boxing or varargs; primitive widening allowed (int → long → float → double).

  2. Phase 2 — boxing / unboxing

    Allow int ↔ Integer, then widening of references (Integer → Number → Object).

  3. Phase 3 — varargs

    Only if nothing matched in phases 1–2.

  4. Most specific

    If several match in the same phase, the most specific wins; if none is more specific → ambiguous compile error.

Java
public class Main {
    static void f(long x)    { System.out.println("long (widening)"); }
    static void f(Integer x) { System.out.println("Integer (boxing)"); }
    static void f(int... x)  { System.out.println("int... (varargs)"); }

    static void g(Object o)  { System.out.println("g(Object)"); }
    static void g(String s)  { System.out.println("g(String)"); }

    static void h(double d)  { System.out.println("h(double)"); }
    static void h(Object o)  { System.out.println("h(Object)"); }

    public static void main(String[] args) {
        f(5);              // widening beats boxing beats varargs
        f(Integer.valueOf(5));
        f();
        g(null);           // String is more specific than Object
        g((Object) "hi");  // static (compile-time) type decides
        h('A');            // char → double widening wins over boxing to Character
    }
}
Output
long (widening)
Integer (boxing)
int... (varargs)
g(String)
g(Object)
h(double)
Java
public class Main {
    static void k(Integer a, long b) {}
    static void k(long a, Integer b) {}

    public static void main(String[] args) {
        k(1, 2);          // error: reference to k is ambiguous
    }
}

A classic trap: List.remove

Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(List.of(10, 20, 30, 1));
        list.remove(1);                       // remove(int index) → removes 20
        System.out.println(list);
        list.remove(Integer.valueOf(1));      // remove(Object) → removes the value 1
        System.out.println(list);
    }
}
Output
[10, 30, 1]
[10, 30]

Can we overload main?

What is the priority order in overload resolution?

Is void f(int[] a) vs void f(int... a) a valid overload?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report