Referencing a child object to a variable of type parent in Java can be real confusing.

Here is an example of two classes Person and Student and an overriden method whatAmI:

class Person {
    String it = "It is a Person.";
    public void whatAmI(Object x) {
        System.out.print("Person's object... " + it);
    }
}

class Student extends Person {
    String it = "It is a Student.";
    public void whatAmI(Object x) {
        System.out.print("Student's object... " + it);
    }
}

public class Calling {
    public static void main(String[] args) {
        Student s1 = new Student();
        Person p1 = new Student();

        p1.whatAmI(s1);
    }
}

When run, the above produces:

Student's object... It is a Student.

With the above example, the overriden method from the child class is used. This might be intuitive and makes sense.

Though, if we overload the method whatAmI and NOT override it:

class Person {
    String it = "It is a Person.";
    public void whatAmI(Object x) {
        System.out.print("Person's object... " + it);
    }
}

class Student extends Person {
    String it = "It is a Student.";
    public void whatAmI(Student x) {
        System.out.print("Student's object... " + it);
    }
}

public class Calling {
    public static void main(String[] args) {
        Student s1 = new Student();
        Person p1 = new Student();

        p1.whatAmI(s1);
    }
}

Then the output is:

Person's object... It is a Person.

The above is not following the logic from to the previous example with the overriden method. Here because of the reference type, the method whatAmI from the parent class is used. And this is just because we have overloaded the method.

As for the String property it, it is always bound to the type of reference. If we print p1.it, the result will be

It is a Person.

To summarise it:

  • Overriden methods are taken from the instantiated object;
  • Overloaded methods are taken from the type of reference;
  • Properties depend of the type of reference.