Ответ 1
Важно различать инициализацию класса и инициализацию объекта.
Инициализация класса
Класс или интерфейс инициализируется после первого доступа, назначая поля постоянной времени компиляции, а затем рекурсивно инициализируя суперкласс (если он еще не инициализирован), затем обработка статических инициализаторов (которые включают инициализаторы для статических полей, которые не являются константами времени компиляции).
Как вы заметили, инициализация класса сама по себе не инициирует инициализацию интерфейсов, которые она реализует. Поэтому интерфейсы инициализируются при первом обращении к ним, как правило, путем чтения поля, которое не является постоянной времени компиляции. Этот доступ может возникать при оценке инициализатора, вызывая рекурсивную инициализацию.
Также стоит отметить, что инициализация не запускается путем доступа к полям, которые являются константами времени компиляции, поскольку они оцениваются в время компиляции:
Ссылка на поле, которое является постоянной переменной (§4.12.4), должно быть разрешено во время компиляции до значения V, обозначенного инициализатором постоянной переменной.
Если такое поле является статическим, тогда никакая ссылка на поле не должна присутствовать в коде в двоичном файле, включая класс или интерфейс, которые объявили это поле. Такое поле всегда должно быть инициализировано (§12.4.2); начальное значение по умолчанию для поля (если оно отличается от V) никогда не должно наблюдаться.
Если такое поле не статично, то никакая ссылка на поле не должна присутствовать в коде двоичного файла, кроме класса, содержащего это поле. (Это будет класс, а не интерфейс, поскольку интерфейс имеет только статические поля.) Класс должен иметь код для установки значения поля V во время создания экземпляра (§12.5).
Инициализация объектов
Объект инициализируется всякий раз, когда создается новый объект, как правило, путем оценки выражения создания экземпляра класса. Это происходит следующим образом:
Назначьте аргументы конструктора новым созданным переменным параметра для этого вызова конструктора.
Если этот конструктор начинается с явного вызова конструктора (§8.8.7.1) другого конструктора в том же классе (с использованием этого), то затем оценивайте аргументы и обрабатывайте вызов конструктора рекурсивно, используя эти пять шагов. Если вызов конструктора завершается внезапно, то эта процедура завершается внезапно по той же причине; в противном случае перейдите к шагу 5.
Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (используя это). Если этот конструктор относится к классу, отличному от Object, то этот конструктор начнет с явного или неявного вызова конструктора суперкласса (используя super). Оцените аргументы и обработайте вызов конструктора суперкласса рекурсивно, используя эти пять шагов. Если вызов конструктора завершается внезапно, то эта процедура завершается внезапно по той же причине. В противном случае перейдите к шагу 4.
Выполните инициализаторы экземпляра и инициализаторы переменных экземпляра для этого класса, присваивая значения инициализаторов переменной экземпляра соответствующим переменным экземпляра в порядке слева направо, в котором они отображаются в текстовом виде в исходном коде для класс. Если выполнение любого из этих инициализаторов приводит к исключению, то никакие новые инициализаторы не обрабатываются, и эта процедура завершается внезапно с тем же исключением. В противном случае перейдите к шагу 5.
Выполните оставшуюся часть тела этого конструктора. Если это выполнение завершается внезапно, то эта процедура завершается внезапно по той же причине. В противном случае эта процедура выполняется нормально.
Как мы видим на шаге 3, наличие явного вызова супер-конструктора просто изменяет конструкцию суперкласса.