Думайте об этом с точки зрения времени выполнения и статических типов:
Animal a = new Cat();
Статический тип (в данном случае записанный слева) переменной a
равен Animal
(вы не можете передать метод, который требует Cat
без даункаста), но тип времени выполнения объекта, на который указывает a
, равен Cat
.
a.getClass()
предоставляет тип времени выполнения (если он помогает думать о нем как о наиболее конкретном подтипе).
Интересно, что перегруженные методы Java разрешаются во время компиляции (без учета типа времени выполнения). Итак, с учетом следующих двух методов:
foo(Cat c);
foo(Animal animal)
Вызов foo(a)
вызовет последнего. Чтобы исправить это, можно использовать шаблон посетителя для отправки на основе типа среды выполнения (двойная отправка).