I wrote the following piece of code:
class Plane {}
class Airbus extends Plane {}
public class Main {
    void fly(Plane p) {
        System.out.println("I'm in a plane");
    }
    void fly(Airbus a) {
        System.out.println("I'm in the best Airbus!");
    }
    public static void main(String[] args) {
        Main m = new Main();
        Plane plane = new Plane();
        m.fly(plane);
        Airbus airbus = new Airbus();
        m.fly(airbus);
        Plane planeAirbus = new Airbus();
        m.fly(planeAirbus);
    }
}
And the result is:
I'm in a plane
I'm in the best Airbus!
I'm in a plane
Unsurprisingly the two first invocations give I'm in a plane and I'm in the best Airbus! respectively.
Plane planeAirbus = new Airbus();
The method treats this object as a Plane, even though the real object is an Airbus. Even when I add abstract to  class Plane, nothing changes and the result of last invocation is still I'm in a plane
So the question is why polymorphism doesn't work in method arguments and invocations? Is there any purpose of that? How does it work?
 
     
     
     
     
     
    