38

I found two examples in my book of overloading methods, but it doesn't explain clearly exactly why it's useful:

package keepo;
public class Main{
    public static void main(String [] args)
    {
        int newScore = calculateScore("Tim", 500);
        System.out.println("New Score is" + newScore);
        calculateScore(75);

    }
    public static int calculateScore(String playerName, int score){
        System.out.println("Player" + playerName +"Has score" + score);
        return score * 1000;
    }
    public static int calculateScore(int score){
        System.out.println("Unnamed player scored" + score + "points");
        return score * 1000;
    }
}

This is pretty straightforward, but honestly it seems pretty useless to method overload here, and it seems just doing it for the sake of doing it.

The next example in the book does method overloading which seems a bit more useful, because that program calculates feet to centimeters, and there is one method where you can put in feet and inches, and one method where you can put inches. However, it still seems just as easy to make two separate methods for this.

That being said, are there any real benefits to doing this? (I read this, but I am not really to satisfied. It seems just as easy to make new methods.)

Community
  • 1
  • 1
Muntasir Alam
  • 1,777
  • 2
  • 17
  • 26
  • 14
    Have a look at `InputStream.read` for some examples... or `PrinterWriter.println`. – Jon Skeet Jul 23 '16 at 01:44
  • 3
    It is "different method" it is just a vehicle so that you do not have to invent unique names for them. For example String.valueOf(int) and String.valueOf(float) would look like String.valueOfInt(int) and String.valueOfFloat(float) - which is just uneeded work for the programmer to invent and remeber the names. – eckes Jul 23 '16 at 01:50
  • The given example is kind of contrived. A real-world scenario would more likely assign each player a *default name* because the possibility of players being "unnamed" is messy. There are, however, plenty of real-world examples of good overloading. A good example might be [`list.add(e)`](http://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-E-) which is essentially equivalent to [`list.add(list.size(), e)`](http://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-int-E-). Most of the time we use the former but sometimes we need to specify an index. – Radiodef Jul 23 '16 at 01:59
  • Possible duplicate of [Why to use Interfaces, Multiple Inheritance vs Interfaces, Benefits of Interfaces?](http://stackoverflow.com/questions/8531292/why-to-use-interfaces-multiple-inheritance-vs-interfaces-benefits-of-interface) – HopefullyHelpful Aug 11 '16 at 17:51
  • I would suggest to stay away from method overloading. Here is a blog post of mine where I argue why: [The Hidden Dangers of Method Overloading](https://www.yegor256.com/2023/08/01/method-overloading.html) – yegor256 Aug 01 '23 at 07:16

6 Answers6

64

I think if you talk about the real benefits of function/method overloading, something without which you won't get your way around, then as you've pointed out in your question, you won't find any.

But how is it helpful? Let's consider this example.

Let's suppose that I'm making an application that finds a person by his name and I declare and define a method

public Person[] findPerson(String name)

Now we get a requirement where we've to find a person by his Date of Birth, so introduce a new method

public Person[] findPerson_byDOB(Date date)

Let's suppose this continues and we've this many methods in my application.

public Person[] findPerson(String name)
public Person[] findPerson_byDOB(Date date)
public Person[] findPerson_byAddress(Address address)
public Person[] findPerson_bySSN(SSN ssn)
public Person[] findPerson_byDepartment(Department department)
public Person[] findPerson_byMobile(Mobile mobile)

It's just one part; this can carry on when we are asked to introduce multiple parameters, like

public Person[] findPerson_byMobileAndAddress(Mobile mobile, Address address)
public Person[] findPerson_byAddressAndDepartment(Address address, Department department)
public Person[] findPerson_byDOBAndDepartment(DOB dob, Department, department)
public Person[] findPerson_byAddressAndDOB(Address address, DOB dob)

and many many more...

While this may seem a little bit exaggerated, trust me, when making an actual industry level application, we may come across a situation when we get hundreds and hundreds of methods like this, and ultimately we'll need a catalog of all these methods of what they actually do.

It is actually a nightmare when we'll have to find the name of all these methods when we would have to use it.

However, when all the parameters are different, we can give same name to the function and it really becomes very easy to remember.

public Person[] findPerson(String name)
public Person[] findPerson(Date date)
public Person[] findPerson(Address address)
public Person[] findPerson(SSN ssn)
public Person[] findPerson(Department department)
public Person[] findPerson(Mobile mobile)
public Person[] findPerson(Mobile mobile, Address address)
public Person[] findPerson(Address address, Department department)
public Person[] findPerson(DOB dob, Department, department)
public Person[] findPerson(Address address, DOB dob)

Now as David pointed out in his answer, we all know how to get String value of integer; probably we have read it somewhere.

static String.valueOf(new Integer(1));

But do you know how many more methods are there that are overloaded with the same name?

static String.valueOf(boolean b)
static String.valueOf(char c)
static String.valueOf(char[] data)
static String.valueOf(double d)
static String.valueOf(float f)
static String.valueOf(int i)
static String.valueOf(long l)
static String.valueOf(Object obj)

The benefits are that you don't have to memorize them all. You don't even have to guess because it's the same name all the way.


EDIT as per Namnodorel's advice

Consider this overloaded method of PrintStream class.

void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(double x)
void println(float x)
void println(int x)
void println(long x)
void println(Object x)
void println(String x)

Just think about the readability if we had to write:

void println_emptyLine()
void println_boolean(boolean x)
void println_character(char x)
void println_characterArray(char[] x)
void println_double(double x)
void println_float(float x)
void println_integer(int x)
void println_long(long x)
void println_object(Object x)
void println_string(String x)
Community
  • 1
  • 1
Raman Sahasi
  • 30,180
  • 9
  • 58
  • 71
  • 2
    Another common examlple is System.out.println() – Namnodorel Jul 23 '16 at 14:19
  • 3
    Great! So its more of a tool for organization and clearness I suppose? – Muntasir Alam Jul 23 '16 at 15:51
  • 1
    Ya, we can say that! – Raman Sahasi Jul 23 '16 at 17:47
  • `public Person[] findPerson(Mobile mobile)` is in there twice; that would be a compilation error, right? – Izkata Jul 23 '16 at 19:37
  • @Izkata - could have suggested an edit instead of leaving a comment, you know. Did so now - it was because `findPerson_byMobileAndAddress` was incorrectly only taking Mobile as a parameter. I suspect that when @RamanSahasi "flattened" the method into an overloaded version that just slipped in. Which, hey - I'll actually take as another point in favour of overloading - the non-overloaded signature was wrong and it completely slipped by. – VLAZ Jul 23 '16 at 21:48
  • @Vld Even though I've approved your edit (as it's clearly correct), there is a general hesitation and resistance to modifying code in another person's post; it's very easy to change characteristics that the author intended. There's nothing wrong with Izkata leaving a comment pointing it out instead. – jpmc26 Jul 23 '16 at 21:59
  • @RamanSahasi This "trust me, when making an actual industry level application, we may come across a situation when we get hundreds and hundreds of methods like this" means poor design. The above is a poor example with a poor justification as other than clarity and readability there are few reasons for overloading. Other languages survive without it. – Oleg Sklyar Jul 23 '16 at 22:30
  • @Vld It's been forever ago since I've used Java; for all I know it's like Python in that it uses the last definition, instead of actually erroring (and if that's the case, it's worth pointing out as something to be careful of when making a lot of overloaded methods). – Izkata Jul 23 '16 at 23:42
  • @jpmc26 Also see my response to Vld – Izkata Jul 23 '16 at 23:44
  • @Izkata xD No, Java is nowhere near like Python. (Python actually just binds function objects to a name; that's why it uses the most recent definition: it just rebinds the name.) Also a good reason to comment instead of suggesting the edit, though. ;) – jpmc26 Jul 24 '16 at 02:35
22

Overloading is useful when you make methods that do the same thing with values of different type.

Math class provides a perfect example - it has groups of function overload by type - four abs, four min, four max, and so on:

int max(int a, int b) {...}
float max(float a, float b) {...}
long max(long a, long b) {...}
double max(double a, double b) {...}

An alternative without overloading would force you to "encode" the type into the name of your method, e.g. Math.intMax(a, b) which would be detrimental to readability of user's code.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @cresjoy See [Access Modifiers](https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) – Sinkingpoint Jul 23 '16 at 02:32
  • The additional benefit is: Let's say you write your own class, and for some reason it makes sense to define the maximum of that class. Thanks to overloading, you can now just write `myObject max(myObject a, myObject b)` instead of having to come up with a new name for `max`. In languages without overloading, it's like "oops, that name is already taken". – cadolphs Jul 23 '16 at 03:02
2

To be simple and concise: Overloading is just a possibility provided by Java (but most of modern and flexible languages use it) (and other languages such as C++ or C#) to allow developers to create for a same method/function name, several of it.

Why ?
Because method naming is important and method naming should convey the behavior of it. So, if two methods have the same behavior (Converting to a String for example) but than one uses a long as input and than the other uses a int as input, why having a different method name ?

    String myString = String.valueOf(new Integer(1));
    String myOtherString = String.valueOf(new Long(2));


The intention and the goal are the same, just the input parameters change.

When overloading is meaningful, you should use it instead of creating some variant clumsy names.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • "most of modern and flexible languages use it"—citation needed. Some popular languages that do not provide method overloading include Python, Ruby, Rust, Haskell, OCaml… these languages often provide other solutions, such as named arguments, that solve the underlying problem that doesn't require relying on static dispatch. (Quick: how might it be in Java that `x == y` but `f(x) != f(y)`, supposing that `f` is pure? [Solution.](https://ideone.com/qwn1DI)) – wchargin Jul 23 '16 at 18:11
  • Sorry, Enter without shift :) @wchargin You are right. I told a stupid thing :) I refer rather to the languages I worked with (C++, Java, C#). About your example, it's an expected behavior insofar as the pure fonction concept is not Java friendly since Java doesn't rely on the Functional Programming concepts. – davidxxx Jul 23 '16 at 18:38
  • @wchargin, I have corrected. Thank you for your precisions :) – davidxxx Jul 23 '16 at 18:47
1

Method overloading is useful in the following scenario:

Consider you have a class that keeps track of a list of names. You have the style of code above, where each method has its own take on performing operations on this list of names.

Suddenly, the internal representation of the list changes (maybe from an array to an ArrayList, it doesn't really matter). Do you want to be the one responsible for refactoring every. single. method?

Method overloading is useful because then you can route all of the operations through a single, generic method. This means that whenever an internal representation changes, you only have to change that generic method, and all your other specialized methods still work the same.


Also, consider your provided example. What happens if you want to change how the program prints the message? You'll have to modify both methods to print the same type of message, a maintenance nightmare. Sure, it seems small now, but think about when your project grows, and you start to have many more methods relying on this (effectively fixed) message format.

Jeeter
  • 5,887
  • 6
  • 44
  • 67
  • So in your first method you print a message, and the same in your second. If you wanted to standardize how you printed those messages, every time you changed the way method 1 printed, you would have to change the way method 2 printed, unless you wanted to keep the old way for method 2. That gets cumbersome trying to maintain many methods, which is why overloading is good in this situation. – Jeeter Jul 23 '16 at 02:01
  • 2
    But I could have taken all of what I wrote in the second or first method make another method, just add an s at the end of the method name and then call it with that name and nothing would change. – Muntasir Alam Jul 23 '16 at 02:04
1

I'm an object and I have a capability, the capability is fixed but can accept various parameters.

If the capability can accept 1000 kinds of parameters, do you want to rack your brains to think about 1000 capability names?

Take others post as a good practice of overload and take what JNIEnv do as a bad practice cause C doesn't support overloading.

CallStaticObjectMethod,
CallStaticObjectMethodV,
CallStaticObjectMethodA,
CallStaticBooleanMethod,
CallStaticBooleanMethodV,
CallStaticBooleanMethodA,
CallStaticByteMethod,
CallStaticByteMethodV,
CallStaticByteMethodA,
CallStaticCharMethod,
CallStaticCharMethodV,
CallStaticCharMethodA,
CallStaticShortMethod,
CallStaticShortMethodV,
CallStaticShortMethodA,
CallStaticIntMethod,
CallStaticIntMethodV,
CallStaticIntMethodA,
CallStaticLongMethod,
CallStaticLongMethodV,
CallStaticLongMethodA,
CallStaticFloatMethod,
CallStaticFloatMethodV,
CallStaticFloatMethodA,
CallStaticDoubleMethod,
CallStaticDoubleMethodV,
CallStaticDoubleMethodA,
CallStaticVoidMethod,
CallStaticVoidMethodV,
CallStaticVoidMethodA,

Reger to JNI for more detailed struct definition

Eugene
  • 10,627
  • 5
  • 49
  • 67
  • 1
    `several of your methods might do similar things but one will take 4 parameters and one will take three` - so? If you call, say `add(5, 7, 56)` and `add(5, 7, 56, 1)` the expectation is that they would both return you the sum of all. There is not a single reason I can think of where you'd want an `add4things(int, int, int, int)` and `add3things(int, int, int)` methods. All overloaded methods should do the same thing, but in slightly different ways. There is no confusion. The signature of the method is part of the contract it has, so `getAge(Tree tree)` and `getAge(Frog frog)` are unambiguous. – VLAZ Jul 23 '16 at 13:49
1

Another reason to overload is to provide one or more default arguments.

Consider the following:

class Something {
    // Imagine that this is a real class, that does real work.

    public void doSomething(boolean b, char c, double d, int i) {
        // Imagine that this is one of the main components of class Something.
        System.out.println("Hi. You passed: " + b + ", " + c + ", " + d + ", and " + i + ".");
    }

    public void doSomething(boolean b, char c, double d) {
        doSomething(b, c, d, 42);
    }

    public void doSomething(boolean b, char c) {
        doSomething(b, c, 1.3579);
    }

    public void doSomething(boolean b) {
        doSomething(b, 'q');
    }

    public void doSomething() {
        doSomething(true);
    }
}

In this example, each overload provides a default for one of the parameters, chaining them together until you get a full call to the version of doSomething() that actually does the work.

Something s = new Something();
Something t = new Something();
Something u = new Something();

// ...

s.doSomething(true, 'c', 2.9);
t.doSomething(false, 'z');
u.doSomething();

See here for an example.