Собеседование по Java — ООП (вопросы и ответы). Часть 2
Вторая часть ответов и вопросов для собеседования по ООП в Java.
Собеседование по Java — ООП (вопросы и ответы). Часть 1
Собеседование по Java — ООП (вопросы и ответы). Часть 3
Вопросы. Часть 2
21. Зачем нужен оператор instanceof?
22. Зачем нужны и какие бывают блоки инициализации?
23. Каков порядок вызова конструкторов и блоков инициализации двух классов: потомка и его предка?
24. Где и для чего используется модификатор abstract?
25. Можно ли объявить метод абстрактным и статическим одновременно?
26. Что означает ключевое слово static?
27. К каким конструкциям Java применим модификатор static?
28. Что будет, если в static блоке кода возникнет исключительная ситуация?
29. Можно ли перегрузить static метод?
30. Что такое статический класс, какие особенности его использования?
31. Какие особенности инициализации final static переменных?
32. Как влияет модификатор static на класс/метод/поле?
33. О чем говорит ключевое слово final?
34. Дайте определение понятию “интерфейс”.
35. Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
36. Почему нельзя объявить метод интерфейса с модификатором final или static?
37. Какие типы классов бывают в java (вложенные… и.т.д.)
38. Какие особенности создания вложенных классов: простых и статических.
39. Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции.
40. В чем разница вложенных и внутренних классов?
41. Какие классы называются анонимными?
42. Каким образом из вложенного класса получить доступ к полю внешнего класса?
Ответы. Часть 2
21. Зачем нужен оператор instanceof?
Оператор instanceof возвращает true, если объект является экземпляром класса или его потомком.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class MainClass { public static void main(String[] a) { String s = "Hello"; int i = 0; String g; if (s instanceof java.lang.String) { // попадем сюда, т.к. выражение будет true System.out.println("s is a String"); } if (i instanceof Integer) { // это отобразится, т.к. будет использована автоупаковка (int -> Integer) System.out.println("i is an Integer"); } if (g instanceof java.lang.String) { // g не инициализирована и поэтому сюда мы не попадем, т.к. // g - null и instanceof вернет false для null. System.out.println("g is a String"); } } |
22. Зачем нужны и какие бывают блоки инициализации?
Блоки инициализации представляют собой наборы выражений инициализации полей, заключенные в фигурные скобки и размещаемые внутри класса вне объявлений методов или конструкторов. Блок инициализации выполняется так же, как если бы он был расположен в верхней части тела любого конструктора. Если блоков инициализации несколько, они выполняются в порядке следования в тексте класса. Блок инициализации способен генерировать исключения, если их объявления перечислены в предложениях throws всех конструкторов класса.
Бывают статические и нестатические блоки инициализации. Также возможно создать такой блок в анонимном классе.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class Foo { static List<Character> abc; static { abc = new LinkedList<Character>(); for (char c = 'A'; c <= 'Z'; ++c) { abc.add( c ); } } } //Пример нестатического блока инициализации class Bar { { System.out.println("Bar: новый экземпляр"); } } //Пример инициализации в анонимном классе JFrame frame = new JFrame() {{ add(new JPanel() {{ add(new JLabel("Хабрахабр?") {{ setBackground(Color.BLACK); setForeground(Color.WHITE); }}); }}); }}; |
23. Каков порядок вызова конструкторов и блоков инициализации двух классов: потомка и его предка?
Сначала вызываются все статические блоки от первого предка до последнего наследника. Потом попарно вызываются динамический блок инициализации и конструктор в той же последовательности (от предка до последнего потомка).
Хорошая картинка, демонстрирующая что происходит на самом деле при инициализации с ресурса javarush.ru:
Вот простенький пример, который это демонстрирует:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
public class Pet { private String name; static { System.out.println("Static block in Pet"); } { System.out.println("First block in Pet"); } { System.out.println("Second block in Pet"); } public Pet() { System.out.println("Pet empty constructor"); } public Pet(String name) { System.out.println("Pet constructor with Name " + name); this.name = name; } } public class Cat extends Pet { private String name; static { System.out.println("Static block in Cat"); } { System.out.println("First block in Cat"); } { System.out.println("Second block in Cat"); } public Cat() { System.out.println("Cat empty constructor"); } public Cat(String name) { super(name); // without this will call super(). Если эту строчку убрать, то будет вызван конструктор Pet(); System.out.println("Cat constructor with Name: " + name); this.name = name; } } public class TestInitOrder { public static void main(String[] args) { Cat cat = new Cat("Rizhick"); } } //Вывод Static block in Pet Static block in Cat First block in Pet Second block in Pet Pet constructor with Name Rizhick First block in Cat Second block in Cat Cat constructor with Name: Rizhick |
24. Где и для чего используется модификатор abstract?
Абстрактным называется класс, на основе которого не могут создаваться объекты. При этом наследники класса могут быть не абстрактными, на их основе объекты создавать, соответственно, можно. Для того, чтобы превратить класс в абстрактный перед его именем надо указать модификатор abstract.
Абстрактный метод — метод, который не имеет реализации. Если в классе есть хотя бы один абстрактный метод, то весь класс должен быть объявлен абстрактным.
1 2 3 4 5 6 7 8 9 10 |
public abstract class Fighter { abstract void fight(); } public class JudoFighter extends Fighter { @Override void fight() { System.out.println("Учу ушу, руками машу! Бью с лету в душу..."); } } |
Использование абстрактных классов и методов позволяет описать некую абстракцию, которая должна быть реализована в других классах. Например, мы можем создать абстрактный класс Fighter и объявить в нём абстрактный метод fight(). Т.к. стилей борьбы может быть много, то, например, для JudoFighter extends Fighter метод fight() будет описывать приемы в стиле дзюдо и т.д.
25. Можно ли объявить метод абстрактным и статическим одновременно?
Нет. Получите: Illegal combination of modifiers: ‘abstract’ and ‘static’. Модификатор abstract говорит, что метод будет реализован в другом классе, а static наоборот указывает, что этот метод будет доступен по имени класса.
26. Что означает ключевое слово static?
Модификатор static говорит о том, что метод или поле класса принадлежат не объекту, а классу. Т.е. доступ можно будет получить и не создавая объекта класса. Поля помеченные static инициализируются при инициализации класса. К примеру, Class.forName(«MyClass», true, currentClassLoader), где второй параметр указывает на необходимость проведения инициализации.
На методы, объявленные как static, накладывается ряд ограничений.
- Они могут вызывать только другие статические методы.
- Они должны осуществлять доступ только к статическим переменным.
- Они не могут ссылаться на члены типа this или super.
27. К каким конструкциям Java применим модификатор static?
- К методу.
- К внутреннему классу.
- К полю.
- К импортируемым классам (с 5-ой java). Например, import static org.junit.Assert.assertThat;
28. Что будет, если в static блоке кода возникнет исключительная ситуация?
Если в явном виде написать любое исключение в static-блоке, то компилятор не скомпилирует исходники. Это все от того, что компилятор умный. В остальном, взаимодействие с исключениями такое же как и в любом другом месте. Если unchecked исключение вывалится в static-блоке, то класс не будет инициализирован.
Какое исключение выбрасывается при ошибке в блоке инициализации?
Для static:
- java.lang.ExceptionInInitializerError — если исключение наследуется от RuntimeException.
Для init:
- exception, который и вызвал исключение, если он наследуется от RuntimeException.
Верно для static и init:
- java.lang.Error — если исключение вызвано Error.
- java.lang.ThreadDeath — смерть потока. Ничего не вываливается.
29. Можно ли перегрузить static метод?
Перегрузить можно, но переопределить нельзя.
1 2 3 4 5 6 7 8 |
public Animal eat() { System.out.println("animal eat"); return null; } public static Animal eat(String s) { System.out.println("test static overload"); return null; } |
30. Что такое статический класс, какие особенности его использования?
Это вложенный класс, который может обращаться только к статическим полям обертывающего его класса, в том числе и приватным. Доступ к нестатическим полям обрамляющего класса может быть осуществлен только через ссылку на экземпляр обрамляющего объекта. К классу высшего уровня модификатор static неприменим.
В примере показано, что для инициализации внутреннего статического класса нет нужды в инициализации родителя. Но в случае обычного внутреннего класса такой номер не пройдет:
1 2 3 4 5 6 7 8 9 10 |
public class Test { class A { } static class B { } public static void main(String[] args) { /*will fail - compilation error, you need an instance of Test to instantiate A*/ A a = new A(); /*will compile successfully, no instance of Test is needed to instantiate B */ B b = new B(); } } |
Статические вложенные классы, не имеют доступа к нестатическим полям и методам обрамляющего класса, что в некотором роде аналогично статическим методам, объявленным внутри класса. Доступ к нестатическим полям и методам может осуществляться только через ссылку на экземпляр обрамляющего класса. В этом плане static nested классы очень похожи на любые другие классы верхнего уровня.
31. Какие особенности инициализации final static переменных?
Переменные должны быть инициализированы во время объявления или в static блоке.
32. Как влияет модификатор static на класс/метод/поле?
Модификатор static говорит о том, что метод или поле класса принадлежат не объекту, а классу.
Внутри static метода нельзя вызвать не статический метод по имени класса.
Про static класс смотрите ответ выше.
33. О чем говорит ключевое слово final?
Может быть применено к полям, методам или классам. В зависимости к какой сущности приложено данное ключевое слово — будет и различный смысл в его применении.
- Для класса. Класс помеченный при помощи final не может иметь наследников.
- Для метода. Метод помеченный при помощи final не может быть переопределен в классах наследниках.
- Для поля. Поле помеченное при помощи слова final не может изменить свое значение после инициализации (инициализируется либо при описании, либо в конструкторе, статическом или динамическом блоке).
- Значение локальных переменных, а так же параметров метода помеченных при помощи слова final не могут быть изменены после присвоения.
34. Дайте определение понятию “интерфейс”.
Ключевое слово interface используется для создания полностью абстрактных классов. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не тела методов.
Наличие слова interface означает, что именно так должны выглядеть все классы, которые реализуют данный интерфейс. Таким образом, любой код, использующий конкретный интерфейс, знает только то, какие методы вызываются для этого интерфейса, но не более того.
1 2 3 4 |
public interface SomeName{ void method(); int getSum(); } |
35. Какие модификаторы по умолчанию имеют поля и методы интерфейсов?
Интерфейс может содержать поля, но они автоматически являются статическими (static) и неизменными (final). Все методы и переменные неявно объявляются как public.
36. Почему нельзя объявить метод интерфейса с модификатором final или static?
Вообще с 8й версии можно static, но нужно чтобы было тело метода. Например
1 2 3 4 5 |
public interface Shape { static void draw() { System.out.println("Wow! It is impossible!"); }; } |
final модификатор просто бессмысленный. Все методы по умолчанию абстрактные, т.е. их невозможно создать не реализовав где-то еще, но это нельзя будет сделать, если у метода идентификатор final.
37. Какие типы классов бывают в java (вложенные… и.т.д.)
38. Какие особенности создания вложенных классов: простых и статических.
- Обычные классы (
Top level classes
) - Интерфейсы (
Interfaces
) - Перечисления (
Enum
) - Статические вложенные классы (
Static nested classes
)- Есть возможность обращения к внутренним статическим полям и методам класса обертки.
- Внутренние статические классы могут содержать только статические методы.
- Внутренние классы-члены (
Member inner classes
)- Есть возможность обращения к внутренним полям и методам класса обертки.
- Не может иметь статических объявлений.
- Нельзя объявить таким образом интерфейс. А если его объявить без идентификатора
static
, то он автоматически будет добавлен. - Внутри такого класса нельзя объявить перечисления.
- Если нужно явно получить
this
внешнего класса —OuterClass.this
- Локальный класс (
Local inner classes
)- Видны только в пределах блока, в котором объявлены.
- Не могут быть объявлены как
private
/public
/protected
илиstatic
(по этой причине интерфейсы нельзя объявить локально). - Не могут иметь внутри себя статических объявлений (полей, методов, классов).
- Имеют доступ к полям и методам обрамляющего класса.
- Можно обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором
final
.
- Анонимные классы (
Anonymous inner classes
)- Локальный класс без имени.
39. Что вы знаете о вложенных классах, зачем они используются? Классификация, варианты использования, о нарушении инкапсуляции.
40. В чем разница вложенных и внутренних классов?
41. Какие классы называются анонимными?
Вложенный класс — это класс, который объявлен внутри объявления другого класса. Вложенные классы делятся на статические и нестатические (non-static). Собственно нестатические вложенные классы имеют и другое название — внутренние классы (inner classes).
Внутренние классы в Java делятся на такие три вида:
- внутренние классы-члены (member inner classes);
- локальные классы (local classes);
- анонимные классы (anonymous classes).
Внутренние классы-члены ассоциируются не с самим внешним классом, а с его экземпляром. При этом они имеют доступ ко всем его полям и методам.
Локальные классы (local classes) определяются в блоке Java кода. На практике чаще всего объявление происходит в методе некоторого другого класса. Хотя объявлять локальный класс можно внутри статических и нестатических блоков инициализации.
Анонимный класс (anonymous class) — это локальный класс без имени.
Использование вложенных классов всегда приводит к некоторому нарушению инкапсуляции — вложенный класс может обращаться к закрытым членам внешнего класса (но не наоборот!). Если это обстоятельство учитывается в архитектуре вашего приложения, не стоит уделять ему особого внимания, поскольку внутренний класс всего лишь является специализированным членом внешнего класса.
Подробнее http://www.quizful.net/post/inner-classes-java
42. Каким образом из вложенного класса получить доступ к полю внешнего класса?
Если вложенный класс не статический и поле не статическое, то можно просто обратиться к этому полю из внутреннего класса, если только у внутреннего класса не существует поля с таким же литералом, в этом случае нужно обращаться через ссылку на внешний класс так — OuterClass.this.имяПоля
*Из комментария к статье: достаточно, чтобы класс был не статическим, а поле статическое или нет — значения не имеет для Member Inner Class.
Собеседование по Java — ООП (вопросы и ответы). Часть 1
Собеседование по Java — ООП (вопросы и ответы). Часть 3
7 thoughts on “Собеседование по Java — ООП (вопросы и ответы). Часть 2”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
Мне кажется в вопросе:
42. Каким образом из вложенного класса получить доступ к полю внешнего класса?
Ответ начинается:
Если вложенный класс не статический и поле не статическое, то можно просто обратиться к этому полю из внутреннего класса
В чем ошибка:
Достаточно, чтобы класс был не статическим, а поле статическое или нет значение не имеет для Member Inner Class.
32. Как влияет модификатор static на класс/метод/поле?
Перезаписать такое поле повторно нельзя (инициализируется один раз).
Это относится к final, но не к static.
38. Какие особенности создания вложенных классов: простых и статических.
… Внутренние статические интерфейсы могут содержать только статические методы…
Если не ошибаюсь, то во внутренних статических интерфейсах могут содержаться нестатические методы.
33. Для поля. Поле помеченное при помощи слова final не может изменить свое значение после инициализации (инициализируется либо при описании, либо в конструкторе/статическом блоке).
А так же в динамическом блоке!
Не понял формулировки. Не могли бьі Вьі прояснить, пожалуйста?
В ответе на 30-ый вопрос ошибка — Вы пытаетесь создать внутренний класс в статическом контексте (метод main). В нестатическом методе A a = new A() создается без проблем
Объявить свой класс
final
— Предотвращает расширение класса, поскольку расширение статического класса не имеет смыслаСделать конструктор
private
— предотвращает создание экземпляра по клиентскому коду, поскольку нет смысла создавать статический классСоздайте все элементы и функции класса
static
. Поскольку класс не может быть инстанцирован, методы экземпляров не могут быть вызваны или доступны поля экземпляраОбратите внимание, что компилятор не помешает вам объявить экземпляр (нестатический). Проблема будет появляться только в том случае, если вы попытаетесь вызвать член экземпляра
Простой пример статического класса в Java