javapolymorphismoverloadingoverridingmethod-dispatch

Overloading is compile-time polymorphism. Really?


I do know the syntactical difference between overriding and overloading. And I also know that overriding is run-time polymorphism and overloading is compile-time polymorphism. But my question is: "Is overloading is really compile-time polymorphism? Is the method call really solving at compile time?". To clarify my point, let's consider an example class.

public class Greeter {
    public void greetMe() {
        System.out.println("Hello");
    }

    public void greetMe(String name) {
        System.out.println("Hello " + name);
    }

    public void wishLuck() {
        System.out.println("Good Luck");
    }
}

Since all of the methods greetMe(), greetMe(String name), wishLuck() are public, they all can be overriden(including overloaded one), right? For example,

public class FancyGreeter extends Greeter {
    public void greetMe() {
        System.out.println("***********");
        System.out.println("*  Hello  *");
        System.out.println("***********");
    }
}

Now, consider the following snippet:

Greeter greeter = GreeterFactory.getRandomGreeter();
greeter.greetMe();

The getRandomGreeter() method returns a random Greeter object. It may either return an object of Greeter, or any of its subclasses, like FancyGreeter or GraphicalGreeter or any other one. The getRandomGreeter() will create the objects either using new or dynamically load the class file and create object using reflection(I think it is possible with reflection) or any other way that is possible. All of these methods of Greeter may or may not be overriden in subclasses. So the compiler has no way to know whether a particular method(overloaded or not) is overriden. Right? Also, wikipedia says on Virtual functions:

In Java, all non-static methods are by default "virtual functions". Only methods marked with the keyword final, which cannot be overridden, along with private methods, which are not inherited, are non-virtual.

Since, virtual functions are resolved at run-time using dynamic method dispatch, and since all non private, non final methods are virtual(whether overloaded or not), they must be resolved at run-time. Right?

Then, How can overloading still be resolved at compile-time? Or, is there anything that I misunderstood, or am I missing?


Solution

  • Overloaded methods can still be overridden, if that is what you ask.

    Overloaded methods are like different families, even though they share the same name. The compiler statically chooses one family given the signature, and then at run time it is dispatched to the most specific method in the class hierarchy.

    That is, method dispatching is performed in two steps:

    If the method arguments types are not covariant at all, overloading is equivalent to having methods names mangled at compile time; because they are effectively different methods, the JVM won't never ever dispatch them interchangeably depending on the type of the receiver.