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

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

Стаття з групи Random UA
І знову всім привіт! Продовжуємо шукати відповіді на 250+ питань для Junior, Middle та Senior розробників. Запитання досить цікаві, і мені самому подобається їх розбирати: у такі моменти можна виявити прогалини в теоретичних знаннях, причому у найнесподіваніших місцях. Розбір питань та відповідей на співбесіді.  Частина 2 - 1З попередньою частиною можна ознайомитись у цій статті . Але перш ніж ми почнемо, я хочу нагадати, що:
  1. Питання, які перетинаються з цією серією статей , я пропускатиму, щоб зайвий раз не дублювати інформацію. Рекомендую прочитати ці матеріали, тому що там представлені найчастіші (популярні) питання для співбесід Java Core.
  2. Питання на DOU представлені українською, але у мене тут буде все російською.
  3. Відповіді можна було й розписати докладніше, але я не буду, тому що тоді відповідь на кожне запитання може затягнути цілу статтю. Та й так докладно вас на жодному соцзабезі не запитають.
За потребою залишатиму посилання, для більш глибокого вивчення. Полетіли!

11. Назвіть усі методи класу Object

Клас Object має 11 методів:
  • Class<?> getClass() - Отримання класу поточного об'єкта;
  • int hashCode() — отримання хеш-коду поточного об'єкта;
  • boolean equals (Object obj) - Порівняння поточного об'єкта з іншим;
  • Object clone() — створення та повернення копії поточного об'єкта;
  • String toString() - Отримання рядкового подання об'єкта;
  • void notify() - пробудження одного потоку, що очікує на моніторі даного об'єкта (вибір рандомного потоку);
  • void notifyAll() — пробудження всіх потоків, що очікує моніторі даного об'єкта;
  • void wait() - перемикає поточний потік в режим очікування (заморожує його) на поточний монітор, працює тільки в synchronized блоці, поки який-небудь notify або notifyAll не розбудить потік;
  • void wait(long timeout) - також заморожує поточний потік на поточний монітор (на поточний synchronized), але вже з таймером виходу з цього стану (ну або знову ж таки: поки notify або notifyAll не розбудить);
  • void wait (long timeout, int nanos) - метод, аналогічний вищеописаному, але з більш точним таймерів виходу із заморозки;
  • void finalize() - перед видаленням цього об'єкта збирачем сміття викликається цей метод (наостанок). Він використовується для очищення ресурсів, що займаються.
Для коректного використання методів hashCode , equals , clone , toString , finalize їх необхідно перевизначати, враховуючи поточне завдання та обставини.

12. У чому різниця між try-with-resources і try-catch-finally під час роботи з ресурсами?

Як правило, при використанні try-catch-finally блок final застосовували для закриття ресурсів. У Java 7 з'явився новий вид оператора try-with-resources , аналог try-catch-finally для звільнення ресурсів, але більш компактний і легкочитаний. Давайте пригадаємо, як виглядає try-catch-finally :
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
А тепер давайте перепишемо цей код, але з використанням try-with-resources :
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
Якось простіше стало, не знаходите? Крім спрощення, ще є кілька моментів:
  1. У try-with-resources ресурси, оголошені в дужках (які будуть закриті) повинні імплементувати AutoCloseable інтерфейс і його єдиний метод — close() .

    Метод close виконується у неявному finally блоці , інакше як програма зрозуміє, як саме цей закривати ресурс?

    Але, швидше за все, ви рідко писатимете свої імплементації ресурсів та їх метод закриття.

  2. Послідовність виконання блоків:

    1. Блок try .
    2. Неявний finally .
    3. Блок catch , який ловить винятки у попередніх кроках.
    4. Явний finally .

    Як правило, винятки, які випали нижче за списком, перебивають ті, що випали вище.

Уявіть ситуацію, що при використанні try-catch-finally у вас у try падає виняток. Відповідно, відразу починає виконуватися певний блок catch , в якому ви прописуєте інший виняток (наприклад, з повідомленням, яке детальніше описує помилку), і ви хочете, щоб метод прокидав цей виняток далі. Далі йде виконання блоку finally , і в ньому теж падає виняток. Але вже інше. Яке з цих двох винятків у результаті викине цей спосіб? Виняток, що викинув блок finally ! Але і тут є один момент з try-with-resources . Тепер розглянемо поведінку try-with-resourcesу цій самій ситуації. У нас падає виняток у блоці try при спробі закриття ресурсів у методі close() , тобто у неявному finally . Яке ж із цих винятків відловить catch ? Те, що викинув блок try ! Виняток із неявного finally (з методу close() ) ігноруватиметься. Це ігнорування ще називають придушенням винятків.

13. Що таке побітові операції?

Побітові операції - це операції над ланцюжками бітів, які включають логічні операції і побітові зрушення. Логічні операції:
  • побітове І - порівнює бітові значення, і по ходу цього будь-який біт, встановлений в 0 (false), встановлює відповідний біт в результаті як 0. Тобто якщо в обох порівнюваних значеннях біт був 1 (true), в результуючому теж буде 1.

    Позначається як - AND , &

    Приклад: 10111101 & 01100111 = 00100101

  • побітове АБО - операція, зворотна попередньої. Будь-який біт, встановлений в 1, встановлює аналогічний біт в результаті як 1. І, відповідно, якщо в обох порівнюваних значеннях біт був 0, в результуючому теж буде 0.

    Позначається як - OR , |

    Приклад: 10100101 | 01100011 = 11100111

  • побітове НЕ - застосовується до одного значення, перевертає (інвертує) біти. Тобто, ті біти, що були 1, стануть 0; а ті, що були 0, стануть 1.

    Позначається як - NOT , ~

    Приклад: ~10100101 = 01011010

  • побітове виключне АБО — порівнює бітові значення, і якщо в обох значеннях біт дорівнює 1, то результат буде 0, також якщо в обох значеннях біт 0, результат буде 0. Тобто, щоб результат дорівнював 1, потрібно, щоб тільки один з бітів дорівнював 1, а другий дорівнює 0.

    Позначається як XOR , ^

    Приклад: 10100101 ^01100011 = 11000110

Побітові зрушення - >> або << зсувають біти значення у вказану сторону, на вказане число. Позиції, що звільнабося, заповнюються нулями. Наприклад:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
Також є виняток при зрушенні праворуч негативного числа. Як ви пам'ятаєте, перший біт відповідає за знак, і якщо цей біт дорівнює 1, число негативне. Якщо ви рухатимете негативне число, позиції, що звільнабося, будуть заповнюватися вже не нулями, а одиницями, тому що необхідно підтримувати знаковий біт. Наприклад: 10100010 >> 2 = 11101000 При цьому в Java існує додатковий оператор беззнакового зсуву вправо >>> Даний оператор - аналог >>, при зрушенні яким позиції, що звільнабося, заповнюються 0, незалежно від того, негативне число або позитивне. Наприклад: 10100010 >>> 2 = 00101000 Детальніше про побітові операції читаємо ось тут . Розбір питань та відповідей на співбесіді.  Частина 2 - 2Як приклади використання побітових зрушень у Java, ви можете навести метод hash()у HashMap, який використовується для визначення спеціального внутрішнього хеш коду ключа: Розбір питань та відповідей на співбесіді.  Частина 2 - 3Цим метод дозволяє рівномірно розподіляти дані в HashMap, щоб мінімізувати кількість колізій.

14. Об'єкти яких стандартних класів є immutable в Java?

Immutable — це об'єкт, який дозволяє змінювати свої початкові параметри. Можливо, він має методи, які повертають нові об'єкти даного типу з параметрами, які ви хотіли змінити. Деякі стандартні immutable об'єкти:
  • безумовно, найвідоміший immutable об'єкт у Java - це String;
  • екземпляри класів-оберток, які обертають стандартні типи: Boolean, Character, Byte, Short, Integer, Long, Double, Float;
  • об'єкти, які зазвичай використовуються для особливо ВЕЛИКИХ чисел - BigInteger і BigDecimal;
  • об'єкт, який є одиницею у стектрейсах (наприклад, у стектрейсі винятків) StackTraceElement;
  • об'єкт класу File може змінювати файли, але при цьому сам по собі він незмінний;
  • UUID – який часто використовується як унікальний id елементів;
  • усі об'єкти класів пакету java.time;
  • Locale — використовується визначення географічного, політичного чи культурного регіону.

15. Які переваги є immutable object перед звичайними об'єктами?

  1. Такі об'єкти — безпечні при використанні багатопоточного середовища . Використовуючи їх, ви можете не турбуватися про те, що буде втрачено дані через стан гонки потоків. На відміну від роботи зі звичайними об'єктами: у такому разі вам доведеться дуже добре продумати та опрацювати механізми використання об'єкта в паралельному середовищі.
  2. Immutable об'єкти є хорошими ключами в map, адже якщо використовувати об'єкт, що змінюється, а потім об'єкт змінить свій стан, при використанні HashMap може виникнути плутанина: об'єкт все ще буде присутній, і якщо використовувати containsKey() , то його можна і не знайти .
  3. Immutable об'єкти відмінно підходять для зберігання незмінних (константних) даних, які в жодному разі не повинні бути змінені під час роботи програми.
  4. "Атомарність по відношенню до збою" - якщо immutable об'єкт викине виняток, то він все одно не залишиться в небажаному (зламаному) стані.
  5. Ці класи прості в тестуванні.
  6. Не потрібні такі додаткові механізми, як конструктор копіювання та реалізація клону.

Питання щодо ОВП

Розбір питань та відповідей на співбесіді.  Частина 2 - 4

16. У чому переваги ОВП у цілому та порівняно з процедурним програмуванням?

Отже, переваги ООП:
  1. Складні програми писати простіше, ніж процедурним програмуванням, так як у нас все розбито на маленькі модулі - об'єкти, які взаємодіють між собою - і в результаті програмування зводиться до взаємовідносин між об'єктами.
  2. Програми, написані за допомогою ООП, набагато простіші у модифікації (при дотриманні концепцій проектування).
  3. Оскільки дані та операції з них утворюють єдину сутність, де вони розмазуються у всьому додатку (що нерідко буває при процедурному програмуванні).
  4. Інкапсуляція інформації захищає найкритичніші дані для роботи від користувача.
  5. Можливе перевикористання одного і того ж коду, з різними даними, адже класи дозволяють створювати безліч об'єктів, кожен з яких має власні значення атрибутів.
  6. Спадкування та поліморфізм також дозволяють перевикористовувати та розширювати вже існуючий код (замість дублювання схожого функціоналу).
  7. Простіша розширюваність програми, ніж при процедурному підході.
  8. Підхід ООП дає змогу абстрагуватися від деталей реалізації.

17. Розкажіть, які недоліки є у ОВП

На жаль, і вони присутні:
  1. ООП вимагає великий обсяг теоретичних знань, який потрібно освоїти, перш ніж ви зможете щось написати.Розбір питань та відповідей на співбесіді.  Частина 2 - 5
  2. Ідеї ​​ООП негаразд прості розуміння і застосування практично (треба бути у душі трохи філософом).
  3. При застосуванні ОВП трохи знижується продуктивність функціонування ПЗ через складнішу організацію системи.
  4. Для ОВП підходу потрібно більше пам'яті, оскільки все складається з класів, інтерфейсів, методів, які займають набагато більше пам'яті, ніж звичайні змінні.
  5. Тимчасові витрати на початковий аналіз більші, ніж при процедурному.

18. Що таке статичний та динамічний поліморфізм

Поліморфізм дає можливість об'єктам поводитися по-різному одного й того класу чи інтерфейсу. Існує два види поліморфізму, які ще відомі як раніше та пізніше зв'язування . Статичний поліморфізм, або раніше зв'язування:
  • відбувається під час компіляції (на ранній стадії життєвого циклу програми);
  • вирішує, який спосіб виконувати під час компіляції;
  • навантаження методу - це приклад статичного поліморфізму;
  • до раннього зв'язування належать приватні, статичні та термінальні методи;
  • успадкування не бере участь у ранньому зв'язуванні;
  • у статичному поліморфізм беруть участь не конкретні об'єкти, а інформація про клас, тип якого представлений зліва від імені змінної.
Динамічний поліморфізм, або пізніше зв'язування:
  • відбувається під час виконання (під час роботи програми);
  • динамічний поліморфізм вирішує, яка саме реалізація буде у методу під час виконання;
  • перевизначення методу - приклад динамічного поліморфізму;
  • пізнє зв'язування - це призначення конкретного об'єкта, посилання його типу або суперкласу;
  • успадкування пов'язане з динамічним поліморфізмом.
Докладніше про відмінності раннього та пізнього зв'язування можна прочитати ось у цій статті .

19. Дайте визначення принципу абстракції у ОВП

Абстракція в ОВП - це спосіб виділити набір значних показників об'єкта, виключивши незначні деталі. Тобто при проектуванні програми з ОВП підходом ви зосереджуєтеся на моделях загалом, без поглиблення деталі їх реалізації. У Java за абстракцію відповідають інтерфейси. Наприклад, у вас є машина і це буде інтерфейс. А різні взаємодії з нею – наприклад, завести двигун, використовувати коробку передач – це функції, які ми використовуємо без заглиблення в деталі реалізації. Адже в той момент, коли ви ведете машину, ви не думаєте, як саме коробка передач виконує своє призначення, або як ключ заводить двигун, або яким чином кермо повертає колеса. І якщо навіть реалізацію однієї з цієї функціональності замінити (наприклад двигун), ви цього можете і не помітити. Вам це не важливо: ви не заглиблюєтесь у деталі реалізації. Вам важливо, щоб дія виконувалася. Власне, це є абстрагування від деталей реалізації. На цьому моменті ми сьогодні і зупинимося: продовження буде!Розбір питань та відповідей на співбесіді.  Частина 2 - 6
Інші матеріали серії:
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ