Java Method Overloading

Not enough people realise that "method overloading" in the JavaLanguage is just a way of having multiple methods with the same name - the overloaded methods do not behave like you'd expect. In an OO language, particularly in Java, where everything is polymorphic, ypu may be used to the right method magically being chosen at runtime, and sometimes confusion can allow this to extend to overloaded methods.

Overloaded methods are completely different from one another, and there is no way that some given line of code could ever invoke one overloaded form of the method on the first invokation and a different form on the second invokation. The compiler fully resolves overloaded methods based the declared types of the arguments to the method invocation at compile time.

Test code PolyTest2.java:

 import java.util.Vector;
 import java.util.Stack;

public class PolyTest2 {

public static void main(String args[]) { new PolyTest2(); }

public PolyTest2() { Vector aVector = new Vector(); Vector aStack = new Stack();

print(aVector); print(aStack); }

public void print(Vector v) { System.out.println("Printing a vector."); }

public void print(Stack s) { System.out.println("Printing a stack."); }

}

I haven't run this code, but it should print:
 Printing a vector.
 Printing a vector.

(This is because both variables are of type Vector. The Compiler decides which overloaded method to call, and when it does, it looks at the types of the variables. Information about what is in the variables isn't normally available until runtime, even though in this case it's pretty obvious what's in them.)

Seeing methods to print a Stack and a Vector and variables containing those types, however, it would make sense to see:

 Printing a vector.
 Printing a stack.

This is somewhat confusing. It also occasionally leads to the need to cast a value to a particular type when calling an overloaded method so that the compiler can prove that it will be of that type and properly resolve the overloaded method - it looks particularly strange to see:

 super((SomeClass) null, 0, 1);

as one sometimes does in constructors. Why on earth, some people have asked, do you need to cast null? But you do, if you have an overloaded method or multiple constructors (which can be considered more or less as a overloaded static methods)

Contributors: EmlynShannon, EricHodges, JonathanTang, EdwardKiser


I don't understand this page. Why would anyone expect Java to behave other than it does? -- EricHodges

Maybe you can't understand why, but they do. I guarentee that they do. Although it is just possible that one such person will read this page and see their own folly. --EmlynShannon

Which languages don't behave this way? -- EricHodges

It's not a matter of being able to make a complete, working language which would work differently to Java - it's a matter of neglecting to think it through. The Java Runtime chooses which virtual method it should use "by magic", at runtime. So why shouldn't it, "by magic" choose which overloaded method it should use? There is a good reason why, but you need to think it through.

Explain it to me. Java does choose which overloaded method is should use, using the same "magic" it uses to pick "virtual" methods (since every method in Java is a "virtual" method). I've been using Java since it came out and have never met anyone that thought a method would be selected by the type(s) of the object(s) instead of the type(s) of the variable(s). Where does that assumption come from? Is there some other language that behaves like that? -- EricHodges

See MultiMethods for a list of programming languages that are polymorphic in all arguments.

Whether or not this behavior is a problem probably depends on how a programmer's taught. I learned from C++ For Dummies, which was very careful to explain the difference between overloading and overriding, and taught overloading before it even got to polymorphism. When polymorphism was introduced, it was solely in the context of a method "belonging" to an object. As a result, I never had the idea that other parameters could be polymorphic, at least not till I started studying more advanced languages. The book even explained that the compiler just renames overloaded functions behind the scenes, and there's no run-time magic going on.

But if someone is first introduced to OO by learning about the *this pointer, and how

  obj.method(arg1, arg2);
is really just syntactic sugar for
  method(obj, arg1, arg2);
then they could be in trouble. Because then they learn about polymorphism, and how the compiler can magically select methods at run-time, and they wonder why that just applies to the first argument and not any of the others. It seems like a rather arbitrary distinction, to privilege that one argument over the others.

This is one case where I've found Java/CeePlusPlus/SmallTalk's use of a PrimaryNoun syntax to be quite handy. If I had to remember manually that only the first argument was bound dynamically, I'd go bonkers. --JonathanTang

I've never worked with MultiMethods, and the wiki page doesn't explain them in any detail. Do they select a method based on the reference variable type or object type? -- EricHodges

They select based on the dynamic type of the object. CommonLisp and DylanLanguage both have SoftTyping (you aren't required to include any type declarations, though you can for performance or error-checking purposes), and so it wouldn't make sense to dispatch on the static type (which, when prototyping, is often a simple <object>). --JonathanTang


(refactoring in progress)

Anyone thinking that the right version of a method will be magically chosen at runtime may get burned by overloaded methods because the compiler chooses which of the overloaded versions of the method to invoke - it isn't chosen at runtime. And yes, I have known people that have burned their fingers on this, I swear I am not making this up.

Your confusion stems from not misunderstanding this concept, while I'm trying to warn the reader - who I am assuming may have misunderstood.

So, once again. Java does the right thing. Some people who aren't thinking clearly don't realise that, and don't realise why that is the right thing. -- EmlynShannon

I have known people who are not novices get burned on this, so I thought I'd add it to WikiWikiWeb. Mainly it's people who haven't used Java much but know so much about other languages that they can't be called novices (and can't possible stoop to asking for help, either).


Actually, the more I learn about and program in DylanLanguage, the more convinced I am that Java does the WrongThing. Dylan supports MultiMethods, and far from leading to SpaghettiCode, I find that it lets me reason about really simple, one-line methods at a time. I just declare all the types of the arguments, and don't even worry about which method belongs to which class (methods don't belong to any class in Dylan). See DoubleDispatchExample. The compiler will select the right method based on whatever the run-time types of the parameters are. It made me nervous before I'd actually tried programming with it, but after 50-100 lines of code it felt really natural. --JonathanTang

What WrongThing does Java do? -- EricHodges


See SingleDispatch, MultipleDispatch


EditText of this page (last edited December 9, 2005) or FindPage with title or text search