Object obj1 = new ClassA();
In this line, Object is considered the static type of the variable, and ClassA is considered the dynamic type of the variable.
Static types are always used to guarantee the existence of a field or method by the compiler, while dynamic types are what's actually used to call methods when the program runs.
The idea is this: since the static type must always be a superclass of the dynamic type, the static type is used to guarantee that no matter what subclasses you use as the dynamic type of the variable, they will always at least support the methods of the superclass. For example, every Object has a hashCode() method and a toString() method, because these methods are considered essential to all objects in Java. You would always be allowed to call obj1.hashCode().
Because the Object class does not contain a whoAmI() method, however, the compiler will throw an error.