Уровень 24. Ответы на вопросы к собеседованию по теме уровня
Анонимные внутренние классы компилируются в файлы внешнийКласс$n.class . На месте внешнего класса, соответственно, название обрамляющего класса, внутри которого описывается анонимный внутренний класс. На месте n число от 1 до количества анонимных классов.
Можно ли наследовать внутренние классы?
Наследовать внутренние классы от других — можно.
Наследование от внутреннего класса получается чуть сложнее, чем обычное, так как конструктор внутреннего класса связывается со ссылкой на окружающий внешний объект. Проблема состоит в том, что «скрытая» ссылка на объект объемлющего внешнего класса должна быть инициализирована, а в производном классе больше не существует объемлющего объекта по умолчанию. Для явного указания объемлющего внешнего объекта применяется специальный синтаксис:
Здесь класс InheritInner расширяет только внутренний класс, а не внешний. Но когда дело доходит до создания конструктора, предлагаемый по умолчанию конструктор не подходит, и вы не можете просто передать ссылку на внешний объект. Необходимо включить в тело конструктора выражение ссылкаНаОбъемлющийКласс.super(); в теле конструктора. Оно обеспечит недостающую ссылку, и программа откомпилируется.
Можно ли наследовать анонимные внутренние классы?
Описывая анонимный класс мы уже наследуемся от какого-то класса или реализуем какой-либо интерфейс. К анонимным классам напрямую нельзя применить слова extends или implements, но ведь никто не мешает заранее подготовиться и расширить нужный интерфейс, который будем реализовывать с помощью анонимного класса. Пример в коде ниже.
Наследоваться от анонимного класса нельзя.
Можно ли переопределять внутренние классы?
Переопределение внутреннего класса, как если бы он был еще одним методом внешнего класса, фактически не имеет никакого эффекта:
Вывод:
Конструктор по умолчанию автоматически синтезируется компилятором, а в нем вызывается конструктор по умолчанию из базового класса. Можно подумать, что при создании объекта BigEgg должен использоваться «переопределенный» класс Yolk , но это отнюдь не так, как видно из результата работы программы.
Этот пример просто показывает, что при наследовании от внешнего класса ничего особенного с внутренними классами не происходит. Два внутренних класса — совершенно отдельные составляющие, с независимыми пространствами имен. Иными словами нельзя.
Какие ограничения есть у локальных классов?
Вначале вспомним что такое локальный класс. Это класс, описанный в блоке кода, то есть, по-простому — между кавычек . Наиболее часто эти кавычки являются телом метода. Но могут они быть и просто блоком, статическим блоком, телом if -ов, циклов и т.д.
Локальный класс наделён особенностями внутренних классов, но имеет отличительные черты, а именно:
- он имеет доступ только к финальным полям и аргументам обрамляющего метода, а также ко всем полям обрамляющего класса, в том числе приватным и статическим;
- локальный класс виден и может создаваться только в блоке, в котором описан;
- у локального класса не ставится модификатор доступа;
- не может иметь статических полей, методов, классов (за исключением финальных);
- локальный класс, объявленный в статическом блоке может обращаться только к статическим полям внешнего класса.
Но! Начиная с Java8 мы можем обращаться в локальных классах к не финальным локальным переменным, если они не были изменены до момента инициализации класса. Также теперь стало возможным обращение к не финальным параметрам метода.
Может ли анонимный внутренний класс содержать статические методы?
Нет. У Анонимных внутренних классов, как и у внутренних классов не может быть статических полей, методов. (вспомним, что анонимные классы компилируются в обычные внутренние, а те, в свою очередь, связаны с объектом обрамляющего класса)
Можно ли создать объект внутреннего класса, если у внешнего класса только private конструктор?
Имея подобный код:
Напрямую, в другом классе (вне обрамляющего), конечно, создать объект InnerClass следующим способом не получится:
Но! Что если у нас есть метод, возвращающий экземпляр
В этом случае приватный конструктор нам не помеха для создания объекта InnerClass . Так же мы без проблем сможем создавать его в методах и в других внутренних классах, принадлежащих PrivateConst . Ответ — можно, если каким-либо способом нам удастся получить объект обрамляющего класса.
Можно ли объявлять внутренние классы private ?
PS Обоснования так и не нашел, но на философии java встречались подобные примеры. Плюс IDE не ругается. Буду признателен за обоснование, но предположу, что в этом плане внутренний класс ничем не отличается от обычного класса.
Можно ли объявлять анонимные внутренние классы private ?
Аналогично (в плане не нашел обоснования). Можно объявить private переменную от типа которой наследуется наш анонимный класс.
Сколько у класса максимально может быть внутренних классов?