Вопросы к собеседованию Java
7 subscribers
12 photos
3 videos
2 links
Канал о Java. Не забудь подписаться :)
Download Telegram
Что будет, если переопределить equals() не переопределяя hashCode()? 🤔

Классы и методы, которые используют правила данного контракта могут некорректно работать, потому что перед тем как сравнить объекты по equals всегда сравнивают/ищут с помощью hashCode. По умолчанию hashCode возвращает уникальное значение для каждого объекта, и если у одинаковых объектов будут разные hashCode сравнение до equals даже не дойдет.
В чем разница между finalize & finally & final?

final - модификатор, который дает:
- Поля не могут быть изменены, методы переопределены;
- Классы нельзя наследовать (а значит и методы переопределить нельзя);
- Применяется только к классам, методам и полям (локальным тоже);
- Аргументы метода указанные final доступны только для чтения, при попытки изменить будет ошибка компиляции;
- final поля необходимо инициализировать сразу (присвоить явно или через конструктор), иначе ошибка;
- Если переменная содержит ссылку на объект и объявлена как final, то содержимое объекта можно менять, а ссылку переменной нельзя (это же справедливо и для массивов)
* если класс final и abstract (взаимоисключающие понятия) возникнет ошибка.

finally - блок в try-catch-finally, который опционален и вызывается в независимости от того вылетело исключение или нет

finalize - метод в классе Object.
В чем отличие i++ и ++i?

++i, i сначала увеличивается на 1, затем участвует в выражении.
i++, i сначала участвует в выражении, затем увеличивается на 1.
Что такое связывание? Как происходит связывание в Java?

Связывание (binding) - присоединение вызова метода к телу метода.

Ранее связывание (early binding) - это связывание, происходящее во время компиляции (также называется static binding). При раннем связывании тип объекта уже должен быть известен. Но так бывает не всегда, если есть иерархия наследования или общий интерфейс.

Например, если есть ссылка на базовый класс, например в качестве аргумента метода, а передается в него класс-потомок, а таких потомков может быть много. Тут компилятор сошел бы с ума, т.к. не знал бы методы какого класса вызывать. Но для разрешения этой проблемы существовал другой вид связывания.

Позднее связывание (late binding) - это связывание, которое выполняется во время выполнения программы (также называют dynamic binding или runtime binding). При позднем связывании определяется фактический тип объекта для вызова именно его метода.

Для всех методов Java используется механизм позднего связывания, если только метод не был объявлен как private Вызов private метода компилируется в инструкцию байт-кода "invokespecial", которая вызывает реализацию метода из конкретного класса, определенного в момент компиляции. Вызов метода с другим уровнем доступа компилируется в "invokevirtual", которая уже смотрит на тип объекта по ссылке в момент исполнения. Финальные неприватные методы тоже вызываются через "invokevirtual". Есть конечно еще несколько других инструкций байт-кода для вызова методов: invokedynamic, invokeinterface и invokestatic.

*Перегрузка метода - это полиморфизм во время компиляции, при котором несколько методов имеют одно и то же имя с разными параметрами или сигнатурой и разным типом возвращаемого значения. Переопределение метода - это полиморфизм среды выполнения, имеющий один и тот же метод с одинаковыми параметрами или сигнатурой, но связанный с сопоставляемыми разными классами.
Что такое оконные функции?

Оконная функция - функция, которая работает с выделенным набором строк (окон, партицией) и выполняет вычисления для этого набора строк в отдельном столбце.

Партиции для каждой оконной функции в запросе могут быть разделены по различным колонкам таблицы.

В отличии от GROUP BY количество строк не уменьшается, а возвращают столько же значений, сколько получили на вход.
Что такое Race Condition?

Race Condition - это ситуация, когда результат выполнения программы зависит от того, в каком порядке выполняются отдельные потоки. При этом несколько потоков конкурируют за доступ к общим ресурсам, таким как переменные, массивы, файлы и т.д., и пытаются изменять их значения. Если при этом не использовать средства синхронизации, то порядок выполнения операций может быть непредсказуемым и привести к неверным результатам.

В примере мы создаем два потока, которые конкурируют за доступ к переменной count объекта класса Counter. Они вызывают метод increment(), который увеличивает значение count на единицу. Ожидаемый результат работы программы - значение count равное 200000. Однако, из-за Race Condition мы можем получить другое значение, например, 199876 или 200123, в зависимости от того, в каком порядке выполняются операции в каждом из потоков.

Чтобы избежать Race Condition в данном примере, можно использовать синхронизацию.
Что такое Date Race и в чем отличие от Race Condition?

Data race (гонка данных) - это проблема, связанная с параллельным доступом нескольких потоков к общему ресурсу, при которой результат выполнения программы зависит от того, какие потоки будут выполняться и в каком порядке.

Data race может возникнуть, когда два или более потока имеют доступ к общему ресурсу и выполняют операции чтения и записи без синхронизации, что может привести к непредсказуемым результатам.

Отличие Race Condition от Data race заключается в том, что Race Condition - это более широкое понятие, которое описывает любую ситуацию, когда результат выполнения программы зависит от порядка выполнения потоков. Data race - это один из видов Race Condition, который возникает при параллельном доступе к общим ресурсам без синхронизации.
Рассмотрим пример с банковским счетом. Допустим, у нас есть банковский счет, на котором находится 100 долларов. Мы хотим произвести две операции: пополнение счета на 50 долларов и снятие со счета 50 долларов. Для этого мы создадим два потока, каждый из которых будет выполнять одну из операций.

В данном случае, мы ожидаем, что счет будет пополнен и снят со счета по 50 долларов, что приведет к ожидаемому результату - остатку на счете в 100 долларов. Однако, из-за Race Condition мы можем получить непредсказуемый результат.

Проблема возникает из-за того, что операции счета не являются атомарными - каждая из операций состоит из нескольких инструкций. В результате, один поток может успеть выполнить только часть операции, прежде чем другой поток начнет свою операцию...
Например, один поток может успеть считать текущий баланс счета (100 долларов), затем другой поток может снять со счета 50 долларов, и первый поток, который должен был пополнить счет, добавит к текущему балансу 50 долларов, не учитывая того, что со счета уже были сняты 50 долларов. В результате, на счете может остаться 100 долларов, если потоки выполняются последовательно, или может быть меньше 100 долларов, если потоки выполняются параллельно.

Отличие от Data race заключается в том, что в данном случае значения переменных не перезаписываются друг другом напрямую, а зависят от порядка выполнения операций.
IoC (Inversion of Control/Инверция управления) - это паттерн, при котором фреймворк берет на себя ответственность за управление объектами (создание, связывание). Т.е. вместо явного создания объектов программистами, контейнер IoC автоматически создает и управляет объектами на основе конфигураций.

Процесс работы IoC в Spring Core включает следующие шаги:

- Конфигурация объектов:
Разработчик определяет конфигурацию объектов, которые будут управляться контейнером IoC. Конфигурация может быть выполнена с использованием различных подходов, таких как XML-файлы, аннотации или Java-код.

- Создание и связывание объектов:
Контейнер IoC анализирует конфигурацию и создает объекты на основе определений, указанных разработчиком. При создании объектов контейнер автоматически удовлетворяет их зависимости, связывая объекты между собой.

- Внедрение зависимостей:
Внедрение зависимостей (Dependency Injection) является ключевым аспектом IoC. Контейнер IoC автоматически внедряет зависимости в объекты, путем предоставления им необходимых ресурсов или ссылок на другие объекты. Это позволяет объектам сосредоточиться на своей основной функциональности, не беспокоясь о создании или поиске зависимостей.

- Управление жизненным циклом:
Контейнер IoC обрабатывает жизненный цикл объектов, управляя их созданием, инициализацией и уничтожением. Он гарантирует, что объекты создаются в нужный момент и освобождаются, когда они больше не нужны. Контейнер может предоставлять различные опции для настройки и управления жизненным циклом объектов.
Spring Core предоставляет ряд аннотаций, которые можно использовать для конфигурации объектов. Некоторые из наиболее часто используемых аннотаций:

@Component: Аннотация, которая указывает, что класс является компонентом и должен быть управляемым контейнером IoC.

@Autowired: Аннотация, которая указывает контейнеру IoC внедрить зависимость в соответствующий объект.

@Qualifier: Аннотация, которая используется вместе с @Autowired для явного указания, какую зависимость следует внедрить, когда есть несколько кандидатов.

@Value: Аннотация, которая позволяет внедрять значения свойств в объект из внешних источников, таких как файлы конфигурации или системные свойства.

@Configuration: Аннотация, которая указывает, что класс является конфигурационным классом, определяющим бины (объекты) в контексте приложения.

Аннотации могут быть применены к классам, полям, методам или конструкторам для указания, как объекты должны быть созданы и связаны в контейнере IoC (в следующих постах рассмотрим это подробнее).
😱 DynamicUpdate аннотация

📝 Используется для оптимизации SQL-запросов UPDATE. Когда эта аннотация применяется к сущности, Hibernate генерирует UPDATE-запросы, которые включают только те поля, которые действительно изменились. По умолчанию Hibernate обновляет все поля объекта, даже если изменилось только одно значение.

Когда использовать?

Если сущность представляет собой таблицу с большим количеством столбцов (10+), и только некоторые из этих столбцов требуется часто обновлять.

При использовании аннотации DynamicUpdate чтобы определить измененные столбцы, Hibernate необходимо отслеживать состояние текущего объекта, что может повлечь за собой накладные расходы. Так что выбирать вам. Или накладные расходы на отслеживание, или на запрос, содержащий все столбцы. Обычно, если много столбцов, то операция записи дорогая, так что это себя оправдывает.  

#Hibernate
🤨3