Skip to content
Theory · Methods · lesson 5 of 8

Method overloading

You have long been using a method that takes anything: System.out.println prints numbers, strings and true alike. In fact these are several different methods with one name, println: for int, for double, for String and other types. Java picks the right one by what stands in the parentheses.

Picture two appliances in a kitchen with the same label, "Heat": a kettle for water and an oven for a pie. You tell the cook "heat" and show what you brought. That alone tells the cook which appliance to switch on.

Your own methods can share a name in the same way. Here are two max methods: one picks the larger of two whole numbers, the other of two fractional ones:

JAVA
public class Main {
    static int max(int a, int b) {
        return a > b ? a : b;
    }

    static double max(double a, double b) {
        return a > b ? a : b;
    }

    public static void main(String[] args) {
        System.out.println(max(3, 7));     // 7
        System.out.println(max(2.5, 1.5)); // 2.5
    }
}

Let's walk through both calls:

  1. In max(3, 7) both arguments are of type int, and the compiler picks max(int a, int b). The method returns 7.
  2. In max(2.5, 1.5) both arguments are of type double, and max(double a, double b) is called. The method returns 2.5.

Without this you would have to invent two names, such as maxInt and maxDouble, and remember which is which.

Overloading and the signature

Overloading means several methods with one name in one class, with different parameter lists. The lists can differ:

  • in the number of parameters: max(int a, int b) and max(int a, int b, int c);
  • in the parameter types: max(int a, int b) and max(double a, double b);
  • in the order of the types: f(int a, double b) and f(double a, int b).

A method's name together with its parameter types is called its signature: for max(int a, int b) it is max(int, int). One class cannot have two methods with the same signature. Parameter names are not part of the signature, and neither is the result type.

How the compiler picks a method

Which of the methods with one name to call is decided by the compiler, before the program runs. It looks only at the arguments in the call: how many there are and what types they have.

An exact match

If a method's parameter types match the argument types, that method is called. This was the case for max(3, 7) and max(2.5, 1.5).

Widening a type

If there is no exact match, the compiler tries to widen the arguments, as Java does in an assignment: int → long → double. A char widens to int as well: in memory a character is stored as a number, its code. Let's look at a call with arguments of different types:

JAVA
System.out.println(max(3, 2.5)); // 3.0

Let's see how the compiler looks for a method that fits:

  1. There is no max(int, double), so there is no exact match.
  2. max(int a, int b) does not fit: 2.5 cannot go into an int without a cast.
  3. max(double a, double b) fits if 3 is widened to 3.0.
  4. The double version is called, so the result prints with a decimal point: 3.0.

If several versions fit after widening, the compiler takes the nearest one along the chain char → int → long → double. For a char argument, the int version is nearer than the long or double versions.

No version fits

If widening does not help either, the program does not compile. For the call max("a", "b") the compiler answers no suitable method found for max(String,String): it does not turn a string into a number.

Here the kitchen picture is off. A cook picks an appliance when they see what you brought. The compiler picks the method earlier, when it reads the program's text, by the types written in it.

Common mistake

Two methods differ only in their result type:

JAVA
static int half(int x) {
    return x / 2;
}

static double half(int x) { // ✗
    return x / 2.0;
}
TEXT
error: method half(int) is already defined in class Main

The program does not compile. Both methods have the signature half(int), and the call half(7) does not tell which one is meant: the compiler picks a method by its arguments only. Whether you can overload a method by changing only its result type is a common interview question, and the answer is "no". Give the methods different names or different parameter types, such as half(double x).

Key points

  • Overloading is several methods with one name and different parameter lists.
  • The signature is the method's name and its parameter types; the result type is not part of it, so methods that differ only in it do not compile.
  • The compiler picks the version before the program runs, by the argument types: an exact match first, then the nearest widening along the chain char → int → long → double.
  • max(3, 2.5) calls the double version: 3 can be widened to 3.0, but 2.5 cannot go into an int.