Java – Why Method Calls Are Based on Reference Type

java

I was just wondering why does Java compiler decide whether you can call a method based on the "reference" type and not on actual "object" type? To explain I would like to quote an example:

class A {
    void methA() {
        System.out.println("Method of Class A.");
    } 
}

class B extends A {
    void methB() {
        System.out.println("Method of Class B.");
    }
    public static void main(String arg[]) {
        A ob = new B();
        ob.methB();       // Compile Time Error
    }
}

This will produce a Compile Time Error that method methB() not found in class A, although Object Reference "ob" contains an object of class B which consists of method methB(). Reason for this is that Java Compiler checks for the method in Class A (the reference type) not in Class B (the actual object type). So, I want to know whats the reason behind this. Why does Java Compiler looks for the method in Class A why not in Class B(the actual object type)?

Best Answer

Your example is in some way a special case. In a non trivial program you can typically not determine the class of the object a certain reference points to better than "it is of the type the reference was declared for or a subtype of it".

The whole concept of polymorphism is based on the fact that the concrete class is only known at runtime but not at compile time. This of course means that the compiler must ensure that the methods that are called on a reference will be available on the referenced object at runtime. The only methods for which this holds true are the methods of the class for which the variable was declared (including all inherited methods from the super classes).

EDIT

As @David said in his comment the reason behind this is that typing is done statically by the programmer in java. If java had type inference the typing would be done by the compiler (but still statically) and your example would be absolutely valid. But it could be invalidated by another line doing this ob = new A().

If java were a dynamic typed language the compiler wouldn't care at all (at compile time) what methods you call on an object.