Бизнес

Как я проходил собеседование на Senior Java

Краткое резюме

Автор статьи рассказывает о своём опыте прохождения собеседования на должность Senior Java Developer и приводит примеры заданий, таких как задача на понимание работы наследования и вопрос о контракте между equals и hashCode.

Здравствуйте! В настоящее время я занимаю должность Senior Java Developer в банковской сфере и за последние годы принял участие в множестве собеседований, которые различались по уровню сложности, стилю проведения и строгости оценки. Хочу поделиться опытом и рассказать об одном из таких собеседований, чтобы помочь тем, кто готовится к подобным испытаниям. В моём профиле есть материалы для подготовки к собеседованиям: 1. **Задача на понимание работы наследования.** Предлагается следующий код: ``` public class First { protected int count; public First() { System.out.println("First"); calculate(); } public void calculate() { System.out.println(count); } @Override public int hashCode() { return 0; } } class Second extends First { public Second() { this.count = 5; System.out.println("Second"); calculate(); } public void calculate() { this.count++; System.out.println(count); } @Override public int hashCode() { return 0; } } class Main { public static void main(String[] args) { Second s = new Second(); } } ``` Что будет выведено при выполнении этого кода? **Ответ:** ``` First 1 Second 6 ``` **Пояснение:** При создании объекта `Second s = new Second();` сначала вызывается конструктор родительского класса `First`. В конструкторе `First()` метод `System.out.println("First")` выводит «First», а `calculate()` вызывает переопределённый метод из класса `Second`. Затем выполняется конструктор `Second()`, где `this.count = 5` устанавливает значение `count` равным 5, `System.out.println("Second")` выводит «Second», а `calculate()` снова вызывается, увеличивая значение `count`. 2. **Знание контракта между `equals` и `hashCode`.** Рассмотрим следующий код (используются те же классы, что и в предыдущей задаче): ``` public static void main(String[] args) { HashSet set = new HashSet<>(); set.add(new First()); set.add(new Second()); set.add(new Second()); System.out.println("Размер: " + set.size()); } ``` **Ответ:** Размер: 3 **Пояснение:** - `new First()` добавляется в набор (хэш-код равен 0). - `new Second()` проверяется: хэш-код также равен 0, но `equals()` по умолчанию сравнивает ссылки, и так как объекты разные, новый объект добавляется в набор. - `new Second()` создаёт ещё один новый объект: хэш-код снова равен 0, но `equals()` определяет, что это третий уникальный объект, и добавляет его в набор. Метод `equals()` по умолчанию (из класса `Object`) сравнивает ссылки на объекты, а не их содержимое. Поэтому каждый `new Second()` создаёт новый объект с новой ссылкой, и все они считаются разными. Важно отметить, что даже если хэш-коды не будут совпадать, размер набора всё равно будет равен 3. Однако, если переопределить методы `equals` и `hashCode` с помощью аннотации `@EqualsAndHashCode` из Lombok, результат изменится на Size: 2. 3. **Устройство `HashMap`.** `HashMap` представляет собой массив корзин. Индекс выбирается по хэш-коду, а столкновения (коллизии) решаются сравнениями через `equals`. **Алгоритм вставки:** - Вычисляется хэш-код и определяется корзина. - Если корзина пуста, элемент вставляется. - Если в корзине уже есть элементы, происходит поиск элемента с таким же ключом через `equals`.

Фильтры и сортировка