Поскольку определение функции класса D является более общим, чем C. Функция C принимает параметр типа B, но функция D принимает параметр типа A, который является родительским для B. Она является более общей, чем функция, определенная в C.
static class D extends C {
void func(A a){
a.f();
}
}
B b = new B();
C c = new D();
c.func(b);
Переменная c указывает на объект D, поэтому c .fun c (b) вызывает метод, определенный в D. A является родителем B, поэтому вызывается метод B. То же, что и при использовании ссылки A, как показано ниже.
A a = new B();
a.f();