JavaRush /Java блог /Random /Разбор вопросов и ответов с собеседований на Java-разрабо...
Константин
36 уровень

Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8

Статья из группы Random
Практика или теория? Что важнее? Многие скажут, что, конечно, практика важнее. Мол, практикуйтесь до упора и будет вам счастье. Смею с этим не согласиться. Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 1На собеседованиях никто и не узнает, насколько вы круты в практике. Вас будут спрашивать во весь рост именно по теории. И лишь потом, когда вы пройдете все круги собеседований и попадете на проект, вы примените ваши практические скилы. Вы можете возразить: иногда дают тестовое задание и практика таки нужна. Не спорю, их иногда дают, но в том-то и дело, что ИНОГДА, а вот теоретическое собеседование проходит ВСЕГДА. Чувствуете разницу? Поэтому у вас должен быть твёрдый теоретический фундамент под ногами, укреплением которого мы сегодня и продолжим заниматься. А именно — мы продолжим разбор вопросов, которые часто задают на собеседованиях.

71. Что будет, если мы не будем переопределять метод toString() для Enum?

Предположим, у нас есть следующий enum:

public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;
}
Выведем в консоли студента, вызвав у него toString():

System.out.println(Role.STUDENT.toString());
Результат в консоли:
STUDENT
То есть по умолчанию toString() для enum-а — название самой константы.

72. Можно ли указывать конструктор внутри Enum?

Да, конечно. Именно через конструктор и задаются значения внутренних переменных enum. В качестве примера к предыдущему enum добавим два поля — ageFrom и ageTo — чтобы обозначить возрастные рамки для каждой роли:

public enum Role {
   STUDENT(5,18),
   TEACHER(20,60),
   DIRECTOR(40,70),
   SECURITY_GUARD(18,50);
 
   int ageFrom;
   int ageTo;
 
   Role(int ageFrom, int ageTo) {
       this.ageFrom = ageFrom;
       this.ageTo = ageTo;
   }
}

73. В чём разница между == и equals()?

Это один из самых распространенных вопросов на собеседованиях на Java-разработчика. Начнём с того, что когда мы сравниваем простые значения (int, char, double…), мы делаем это через ==, так как переменные содержат конкретные значения и мы их можем сравнить. Да и примитивные переменные не являются полноценными объектами — не наследуются от Object и не имеют метод equals(). Когда мы говорим о сравнении переменных, которые ссылаются на объекты, то == будет сравнивать лишь значение ссылок — на тот же объект они ссылаются или нет. И даже если один объект будет идентичен другому, сравнение через == даст отрицательный результат (false), ведь это другой объект. Как вы поняли, для сравнения ссылочных переменных используется метод equals(). Это один из стандартных методов класса Object, который нужен для полноценного сравнения объектов. Но сразу стоит уточнить: для правильной работы этого метода его нужно переопределить, написав, как именно должны сравниваться объекты данного класса. Если вы не переопределите метод, по умолчанию он будет сравнивать объекты по ==. В IntelliJ IDEA можно переопределять его автоматически (средствами IDEA) —> alt + insert, в появившемся окошке выбираем equals() and hashCode() —> выбираем, какие поля класса должны участвовать —> и вуаля, автоматическая имплементация методов выполнена. Вот пример того, как будет выглядеть автоматически сгенерированный метод equals для простейшего класса Cat с двумя полями — int age и String name:

@Override
public boolean equals(final Object o) {
   if (this == o) return true;
   if (o == null || this.getClass() != o.getClass()) return false;
   final Cat cat = (Cat) o;
   return this.age == cat.age &&
           Objects.equals(this.name, cat.name);
}
Если говорить о разнице == и equals для enum-ов, её особо и нет.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 2Ведь enum хранит константы, и даже сравнивая через == аналогичные значения, мы будем получать true, так как ссылки будут всегда на одни и те же объекты. Ну и при использовании equals у нас также будет правильно отрабатывать функционал, тем более если вы зайдёт в тело метода equals для enum-а, увидите, что в классе Enum реализация метода следующая:Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 3То есть внутри — старое доброе сравнение по ссылкам! Подводя итог: для enum сравнение и через ==, и через equals корректное.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 4

74. Что делает метод ordinal() в Enum?

При вызове метода int ordinal() на элементе enum-а мы получим порядковый номер с нуля этого значения в общем ряде перечислений. Давайте используем данный метод на одном элементе из предыдущего рассмотренного enum-а — Role:

System.out.println(Role.DIRECTOR.ordinal());
Соответственно, в консоли выведется:
2

75. Можно ли использовать Enum c TreeSet или TreeMap в Java?

Использование enum типов в TreeSet и TreeMap допустимо. И мы можем написать:

TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
И в консоли будет выведено:
STUDENT TEACHER DIRECTOR SECURITY_GUARD
Мы получили вывод не по алфавиту. Дело в том, что если мы используем элементы enum-а для значений TreeSet или как ключи для TreeMap, элементы сортируются по их естественному порядку (по порядку, в котором они и заданы в enum). Понимание этих особенностей помогает нам писать код качественнее.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 5

76. Как связаны методы ordinal() и compareTo() в Enum?

Как было сказано ранее, ordinal() возвращает порядковый номер значения в общем списке перечислений. Также в разборе предыдущего вопроса вы увидели, что элементы перечислений, попав, например, в TreeSet (отсортированное множество) принимают порядок, в котором они объявлены в enum. И как мы знаем, TreeSet и TreeMap сортируют элементы посредством вызова у них метода compareTo() интерфейса Comparable. Из этого можно сделать предположение, что класс Enum имплементирует интерфейс Comparable, реализуя его в метод compareTo(), внутри которого и используется ordinal() для задания порядка сортировки. Зайдя в класс Enum, мы видим подтверждение этого:Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 6И тело самого метода:Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 7Метод ordinal() тут не вызывается. Вместо этого используется переменная ordinal — порядковый номер элемента в перечислении. Сам же метод ordinal()Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 8— не более чем геттер для переменной ordinal.

77. Напишите пример EnumM

В вопросах рассмотренных выше я уже приводил примеры enum-ов и не вижу смысла дублировать код (например, вопрос номер 72 про конструктор в enum).

78. Можно ли использовать Enum в switch case?

Можно и нужно! Оглядываясь на свою практику, отмечу, что одним из наиболее частых мест применения enum являются логические конструкции типа switch. В таком случае вы можете предусмотреть все возможные вариации case, и после прописания логики для всех значений enum-а использование оператора default может даже не понадобиться! Ведь если вы используете String или числовое значение, например, типа int, вам может прийти не предусмотренное значение, что в свою очередь невозможно с использованием enum-а. Как бы выглядел switch для рассмотренного ранее примера:

public void doSomething(Role role) {
   switch (role) {
       case STUDENT:
           // некая логика для STUDENT
           break;
       case TEACHER:
           // некая логика для TEACHER
           break;
       case DIRECTOR:
           // некая логика для DIRECTOR
           break;
       case SECURITY_GUARD:
           // некая логика для SECURITY_GUARD
           break;
   }
}

79. Как получить все имеющиеся значения в экземпляре Enum?

Если нужно получить все экземпляры перечисления, есть метод values(), который возвращает массив всех доступных значений определенного enum-а в естественно порядке (в порядке задания в enum). Пример:

Role[] roles = Role.values();
for (Role role : roles) {
   System.out.println(role);
}
В консоли будет вывод:
STUDENT TEACHER DIRECTOR SECURITY_GUARD

Stream API

80.Что такое Stream в Java?

Java Stream — относительно новый способ взаимодействия с потоком данных, который в свою очередь позволяет более удобно и компактно обрабатывать большие данные, а также распараллеливать обработку данных между каким-то количеством потоков, что может дать прирост в производительности в использующем функционале. Более глубоко данную тему в двух словах не рассказать, поэтому я оставлю здесь ссылку на статью, которая вам может погрузиться в данную тему.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 9

81. Назовите основные свойства транзакций

Тема называется — Stream API, но при этом вопрос по транзакции. Хмм… Для начала давайте разберемся, что такое транзакция. Транзакция — это группа последовательных операций с базой данных, которая представляет собой логическую единицу работы с данными. Транзакция может быть выполнена либо целиком и успешно, соблюдая целостность данных и независимо от параллельно идущих других транзакций, либо не выполнена вообще, и тогда она не оказывает никакого эффекта. Итак, у транзакций есть четыре основные свойства, которые сокращенно называют ACID. Давайте разберем, как расшифровывается каждая буква данного сокращения: A — Atomicity — атомарность — данное свойство гарантирует, что никакая транзакция не будет зафиксирована в системе частично. Будут либо выполнены все её подоперации, либо не выполнено ни одной (всё либо ничего). С — Consistency — согласованность — свойство, гарантирующее, что каждая успешная транзакция зафиксирует только допустимые результаты. То есть, это гарантия того, что при успешной транзакции будут выполнены все правила, ограничения которые предъявляет система к конкретным данным, иначе транзакция не будет выполнена и данные в системе вернутся к прежнему состоянию. I — Isolation — изолированность — свойство, которое говорит о том, что во время выполнения транзакции параллельные транзакции не должны оказывать влияния на ее результат. Это свойство ресурсозатратно, поэтому как правило оно выполняется частично, допуская определенные уровни изоляций, которые решают определенные изоляционные проблемы. Подробнее мы это обсудим в следующем вопросе.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 10D — Durability — стойкость — данное свойство гарантирует, что если пользователь получил подтверждение от системы, что транзакция выполнена, он может быть уверен, что сделанные им изменения не отменятся из-за какого-либо сбоя. То есть, вы можете быть уверены, что какой-нибудь сбой операционной системы ничего не сделает с вашими данными, если вы уже получили подтверждение успешного выполнения вашей транзакции.

82. Какие есть уровни изоляции транзакций?

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

  • неповторяющееся чтение — при повторном вызове одной и той же выборки (одного и того же запроса) в рамках одной транзакции полученные данные различаются, что происходит из-за изменений (update) и удалений данных другой транзакцией;

  • грязное чтение — процесс чтения данных, добавленных или измененных транзакцией, которая впоследствии не подтвердится (откатится), т.е. чтение недействительных данных;

  • потерянное обновление — при одновременном изменении одних и тех же данных разными транзакциями теряются все изменения, кроме последнего (напоминает проблему “состояние гонки” в многопоточной среде).

Уровни изоляций транзакций как раз и характерезуются тем, от каких проблем изолированности они защищают. Рассмотрим в виде таблицы уровни изоляций и то, от каких проблем они защищают:
Уровень изоляции Фантомное чтение Неповторяющееся чтение Грязное чтение Потерянное обновление
SERIALIZABLE + + + +
REPEATABLE READ - + + +
READ COMMITTED - - + +
READ UNCOMMITTED - - - +
NONE - - - -
И не забывайте обратную сторону медали: чем больший будет уровень изоляции, тем дольше будут отрабатывать транзакции (при параллельном выполнении нескольких транзакций). Если возникло желание поглубже копнуть эту тему, вот отличная статья, с которой можно начать.

83. Какая разница между Statement и PreparedStatement?

И тут не сильно плавный переход на особенности технологии JDBC. Итак, для начала давайте разберемся, что вообще такое Statement. Это объект, который используется для формирования SQL запросов. В JDBC используется три его вида — Statement, PreparedStatement и CallableStatement. CallableStatement мы сегодня рассматривать не будем: поговорим о различии между Statement и PreparedStatement.
  1. Statement используется для выполнения простых SQL запросов без входящих, динамически вставляемых параметров. PrepareStatement используется с возможностью динамической вставки входных параметров.

  2. Для задания параметров в PreparedStatement входные параметры в запросе прописываются как знаки вопроса, чтобы вместо них потом вставить некоторое значение с помощью различных сеттеров, таких как setDouble(), setFloat(), setInt(), setTime()…. В итоге вы не вставите в запрос данные не того типа.

  3. PreparedStatement “прекомпилирован” и использует кеширование, поэтому его исполнение может происходить немного быстрее, чем запрос из объектов Statement. В результате SQL запросы, которые исполняются часто, в целях улучшения производительности создают в виде объектов PreparedStatement.

  4. Statement уязвим к SQL инъекциям, в то время как PreparedStatement предотвращает их. Подробнее об устранении SQL инъекций и других best practices в безопасности Java читайте в этой статье.

Если вы положили начало в изучении технологии соединения Java приложения с Базой Данных — JDBC, советую начать с этой статьи. Что ж, на данном моменте мы сегодня и сделаем остановку.Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 8 - 11
Другие материалы серии:
Комментарии (6)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Илья Уровень 30
12 июня 2021
thanks a lot)
Anonymous #2552385 Уровень 23
11 июня 2021
Кааак это все можно запомнить?? 😭😭😭
hidden #2641196 Уровень 51
10 июня 2021
Очень полезные статьи, спасибо. Как раз сейчас готовлюсь к марафону интервью.