Method Overloading

Method overloading is simply the process of being able to pass different types of parameter into what appears to be the same method. Consider System.out.println(). This method can take a number of different types auto-complete options for the Java println method

To implement method overloading we simply create methods with the same name, but vary the parameters, for example consider the following code:

String formatAsCurrency(int amount){
    return "£"+amount + ".00";
}
String formatAsCurrency(double amount){
    DecimalFormat format = new DecimalFormat("£0.00");
    return format.format(amount);
}
The methods have the same name, but they have different parameter lists. They could be used as follows:
String amount1 = formatAsCurrency(2.00); //will be £2.00
String amount2 = formatAsCurrency(4);    //will be £4.00

Overload method chaining

Sometimes it is useful to be able to chain the overloaded methods. This can help avoid duplicated functionality. For example, in the above code, should the symbol for the British unit of currency (£) be changed, we would have to update code in two places. An alternat solution might be for the method that takes an int parameter to convert it to a double and then call the method that takes a double. It could therefore be re-written as follows:

String formatAsCurrency(int amount){
    return formatAsCurrency(new Double(amount));
}

Method overloading with subtypes

The principle of operator overloading can also be applied to inherited types. Consider that a class Edam extends a class Cheese, and a Halloumi class does also. The below example class shows we can use overloading to differentiate between Cheeses. (Note that the example is not a particularly good example - it would normally be better for the Cheese class and its subtypes to implement some sort of 'describe' method):

class CheeseDescriber {
    String describe(Cheese cheese){
       return "Made from milk";
    }
    String describe(Edam edam){
        return "Made from milk with holes in";
    }
    String describe(Halloumi halloumi){
        return "Made from sheep and goats milk, often grilled";
    }
}
We could then use the code as follows:
Cheese cheese = new Cheese();
Edam edamCheese = new Edam();

CheeseDescriber cheeseDescriber = new CheeseDescriber();

String cheeseDescription = cheeseDescriber.describe(cheese); //"Made from milk"
String edamDescription = cheeseDescriber.describe(edamCheese); //"Made from milk with holes in"

Overloading with collections

Be aware that if we create a collection of objects of the same type (where some are subtype of the same superclass), then the method appropriate to the supertype will be called. In the above example, if we were to create a collection of cheeses inlcuding Edam and Halloumi in an ArrayList<Cheese> then iterate through it as follows

for (Cheese cheese:cheeses) {
    String description = cheeseDescriber.describe(cheese); //Will always be "Made from milk"
}
In each case the description would simply be "Made with milk". This is because type that has been declared (in this case Cheese) is used when determining (when the programme is compiled) which overloaded method will be called.