Когда вы инициализируете Subclass
, конструктор Superclass
вызывается первым. Суперкласс (более общий) должен быть построен перед подклассом (более конкретным). Имеет смысл, верно?
Теперь в конструкторе суперкласса вызывается foo
. Угадай который foo
называется? Подкласс foo
! Это потому, что вы создаете объект Subclass
, поэтому каждый вызываемый вами метод экземпляра будет вызывать реализацию подкласса из-за полиморфизма .
Итак, подкласс foo
вызывается и пытается вывести str.toLowerCase()
. Обратите внимание, что, поскольку конструктор подкласса еще не был вызван, str
не инициализируется, поэтому имеет начальное значение nil
, в результате чего NullPointerException
.
Если метод подкласса foo
был успешно выполнен, конструктор суперкласса вернулся бы, и конструктор подкласса, наконец, был бы вызван.
Урок дня: Не вызывайте нефинальные методы в конструкторе нефинального класса.