I have 3 classes GrandParent, Parent and Child, where 
Child extends Parent and Parent extends GrandParent
public class Main {
    void test(GrandParent gp){System.out.println("GrandParent");}
    void test(Parent p){System.out.println("Parent");}
    public static void main(String args[]){
        GrandParent obj = new Child();
        Main mainObj = new Main();
        mainObj.test(obj);  // This calls test(GrandParent gp)
        mainObj.test(new Child()); // This calss test(Parent gp)
    }
}
In above code in the 2 calls to test() method both with Child object calls different methods. In one it's doing compile-time and in other run-time binding. This sounds little weird to me. How would you explain this?
Method overloading is compile-time polymorphism.
Method overriding is runtime polymorphism.
In your case, you are overloading two instance methods of class Main. 
However, since I presume in your context Child extends Parent, new Child() instanceof Parent == true hence an instance of Child is a valid argument for the method test with argument type Parent. 
In your first case, you pass a reference type GrandParent in the method test, and the exact type is found. 
In your second case, you pass a reference type Child in the method test. The closest match is Parent, hence test(Parent p) is invoked. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With