classGraduateStudentextendsStudent { //nothing here /* GraduateStudent does not have a toString method Therefore when calling m(new GraduateStudent()), It gets the superclass's method in runtime. */ }
classStudentextendsPerson { public String toString() { return"Student"; } }
classPersonextendsObject { public String toString() { return"Person"; } }
Output
1 2 3 4
Student Student Person java.lang.Object@293e75df
Which implementation is used will be determined dynamically by the Java Virtual Machine (JVM) at runtime.
This capability is known as dynamic binding.
Another example of Runtime polymorphism (dynamic binding)
publicclassTest { publicstaticvoidmain(String args[]) { Aa=newB(); //Type is A but point to B a.p(); //Invoke void p() of B (overrided) Bb=newB(); //Type is B, point to B b.p(); //Invoke void p() of B } }
//Output: BB
Note if the Methods are static, they will not get overrided.
publicclassTest { publicstaticvoidmain(String args[]) { Aa=newB(); //Type is A but point to B a.p(); //Invoke void p() of A because Static Bb=newB(); //Type is B, point to B b.p(); //Invoke Static void p() of B } }
//Output: AB
Recall: when calling static method, we can call the method without new an object.
classTest{ publicstaticvoidmain(String[] args){ //Person aa = new Person(); //Teacher aa = new Person(); //error: incompatible types: Person cannot be converted to Teacher Personaa=newTeacher(); //Teacher aa = new Teacher(); aa.p(44); } }