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

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

Стаття з групи Random UA
Вітання! Як неможливо навчитися керувати літаком без спеціального навчання, так і неможливо стати Java-розробником, не витративши довгий годинник на вивчення необхідної теоретичної бази. Сьогодні ми попрацюємо саме над цим: продовжимо розбір 250+ питань на співбесідах для Java-розробників та, відповідно, відповідей на них. Тут — перша та друга частина розбору. Так, безперечно, можна стати хорошим Java-розробником і без усіх цих питань. Тим не менш, якщо ви добре розберетеся у всіх тонкощах мови Java, це дасть вам перевагу, зробивши бажаним кандидатом в очах вашого майбутнього роботодавця.Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 3 - 1

20. Які елементи язика відповідають за інкапсуляцію?

Як ми пам'ятаємо, інкапсуляція це приховування деталей реалізації класу. Тобто коли наш клас використовується ззовні, внутрішня начинка і логіка не очевидні. І які елементи мови відповідають за це? Звичайно, модифікатори доступу ! Те, що нам потрібно приховати, ми відзначаємо модифікатором private . Наприклад, приватні поля класу або якісь внутрішні методи, що допомагають реалізувати якийсь внутрішній функціонал. А до того, чого ми хочемо надати зовнішній доступ, додаємо модифікатор доступу public . Наприклад, метод, який відповідає за надання якоїсь функціональності (всередині якого може використовуватися безліч приватних методів) або ті ж гетери та сеттери для доступу до приватних полів класу. Ах, та у нас ще є модифікаториdefault та protected , які можна використовувати для більш гнучкого та специфічного налаштування доступів до обраних частин класу.

21. Які елементи мови відповідають за спадкування?

Спадкування – це механізм, який дозволяє створювати класи на основі іншого класу. У Java для цього використовують ключове слово extends . Наприклад, у нас є якийсь клас Cat , і ми хочемо створити його спадкоємця – Lion . У коді це виглядатиме якось так:
public class Lion extends Cat
І це означає, що клас Lion успадковує всі методи та змінні класу Cat , крім статичних. Також до елементів мови, які відповідають за успадкування, можна зарахувати super . Це посилання, аналогічне this , але якщо this посилається на об'єкт, в якому її викликали, то super посилається на поточний об'єкт батька. Як правило super використовується:
  1. Для виклику конструктора суперкласу: наприклад, клас Cat має внутрішню змінну name , яку потрібно проініціалізувати в конструкторі. У конструкторі класу Lion це виглядатиме так:

    public Lion(final String name) {
       super(name);
    }
  2. Для звернення до полів та методів батька: наприклад, у класі Cat у нас є проініціалізоване поле age :

    public class Cat {
       int age = 10;
У той же час у нас є таке ж проініціалізоване поле в Lion :
public class Lion extends Cat {
   int age = 15;
І якщо ми хочемо звернутися з об'єкта Lion до змінної age батьківського об'єкта, це потрібно робити через super :
super.name

22. Які елементи мови відповідають за поліморфізм?

Поліморфізм - це здатність об'єкта однієї сигнатури приймати безліч форм (безліч реалізацій). Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 3 - 2Можна сміливо сказати, що Java за поліморфізм відповідають ключові слова implements і extends . implements — коли ми створюємо наш інтерфейс, ми реалізуємо в якомусь класі одну з його можливих форм, але ж вона не єдина форма, чи не так? Згадаємо, як виглядає застосування implements :
public class Cat implements Animal
І в Cat класі ми повинні реалізувати всі абстрактні методи, представлені в інтерфейсі Animal . Так само й успадкування: у класі-спадкоємці ми можемо перевизначити вже існуючу реалізацію методу. Наприклад: кілька спадкоємців -> кілька різних перевизначень одного й того методу. Ну або суперклас був абстрактним і в нього є якийсь спосіб, який необхідно продавати по-особливому для кожного його спадкоємця. Тобто, можна сказати, що метод прийматиме безліч форм. Також у цьому нам може допомогти інструкція @Override, яка ставиться над реалізованими методами і означає, що хочемо реалізувати чи перевизначити (якщо реалізація вже існує у суперкласі) той чи інший метод суперкласу чи інтерфейсу. Вона не є обов'язковою і використовується для більш легкого виявлення помилок. Цією анотацією ви показуєте компілятору, що хочете перевизначити/імплементувати метод суперкласу/інтерфейсу, і він стежитиме, щоб ви не зробабо помилок у сигнатурі методу.

23. Що таке SOLID? Наведіть приклади

SOLID — акронім із назв п'яти основних принципів дизайну для ОВП, придуманих Робертом Мартіном. S - Single-responsibility principle - принцип єдиної відповідальності, який свідчить, що у класу повинна бути тільки одна мета та єдине призначення. Тобто не варто створювати класи, які роблять усі. У цьому випадку можна відтворити антипаттерн "Божественний об'єкт". Якщо у вас є об'єкт Cat , в ньому повинні знаходитися методи, що взаємодіють тільки з його внутрішньою функціональністю, але ніяк не бізнес-логіка, яка не має відношення до цього інстансу. Наприклад, якесь збереження об'єктів даного типу кудись. Цей зовнішній функціонал (щодо Cat), потрібно виносити в інші класи, якісь послуги, завдання яких - забезпечити бізнес-логіку для об'єктів даного типу. O - Open-closed principle - принцип відкритості/закритості. Він означає, що програмні сутності (класи, інтерфейси) мають бути відкриті до розширення, але закриті для модифікації. Наприклад, нам знадобився функціонал, схожий на функціонал вже існуючого класу Cat , але трохи інший. Замість того, щоб змінювати функціонал класу Cat , при цьому ламаючи місця, в яких він вже задіяний, ми використовуємо успадкування або композицію . Як результат - ми досягли своєї мети з модифікованим функціоналом класу Cat , але при цьому ми не змінабо його і нічого не зламали. L - Liskov substitution principle - принцип підстановки Барбари Лисков. Принцип свідчить, що функція, що використовує базовий тип, повинна мати можливість використовувати підтипи базового типу, не знаючи про це. Наприклад, наш клас Cat повинен бути заміненим будь-яким його спадкоємцем, скажімо, Lion без кардинальної зміни поведінки. Загальна логіка (поведінка) залишається такою самою, але змінюються деталі самої реалізації того чи іншого функціоналу. I - Interface segregation principle- Принцип поділу інтерфейсу. Цей принцип говорить, що краще мати безліч спеціалізованих (вузькоспрямованих) інтерфейсів, ніж один універсальний. Наприклад, користувач реалізує деякий інтерфейс, з якого йому потрібен лише він метод, але при цьому цей інтерфейс має ще дев'ять методів, які ніяк не відносяться до логіки потрібного методу. У такому разі користувачеві потрібно буде реалізувати десять методів інтерфейсу, дев'ять із яких зайві для нього! Натомість краще зробити десять різних інтерфейсів, які можна реалізувати при необхідності. Ну чи не десять, а кілька, які будуть мати методи, тісно пов'язані єдиною метою інтерфейсу. D - Dependency Inversion Principle- Принцип інверсії залежностей. Принцип свідчить, що модулі верхніх рівнів нічого не винні залежати від модулів нижніх рівнів. Ще цей принцип описують як абстракція не повинна залежати від деталей, деталі повинні залежати від абстракції. Тобто ми маємо будувати нашу логіку, посилаючись на інтерфейси, і вже потім у цей функціонал передавати конкретні об'єкти, класи яких і реалізують необхідний інтерфейс. Наприклад, якщо у нас є інтерфейс Cat і деякі його реалізації, скажімо, Lion і HomeCat , ми будуємо нашу логіку взаємодії саме з типом інтерфейсу Cat , і вже потім підставляємо конкретну реалізацію Lion або HomeCat , але ніяк не навпаки.

24. Що таке клас, об'єкт, інтерфейс?

Як ми пам'ятаємо, Java – це ООП мова. Тобто програми на Java побудовані на взаємодії між об'єктами. Виходить, програма — це такий собі мурашник, де кожна мурашка це об'єкт. Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 3 - 3Об'єкти — це деякі згруповані дані, які містять різні методи (функції) для взаємодії з цими внутрішніми даними. А класи це інструкції, шаблони для створення об'єктів. Тобто може бути безліч об'єктів, побудованих за однією і тією ж інструкцією, наповнених різними або однаковими значеннями даних. Якщо наводити приклад із життя, можна сказати, що клас - це креслення будівлі, а об'єкт - конкретно створена будівля з цього креслення. Інтерфейси— це аналоги класів із тією різницею, що з них не можна створити об'єкти. Їхня мета - додати елемент абстракції в Java. Точніше, додати гнучкість у взаєминах класів та об'єктів. Під гнучкістю маємо на увазі описані раніше поліморфізм та абстракцію, які у свою чергу відкривають безліч можливостей для побудови внутрішньої архітектури додатку.

25. Що таке клас POJO? Наведіть приклад такого класу

Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 3 - 4POJO - Plain Old Java Object - старий добрий Java-об'єкт: простий об'єкт, класу, який не успадкований від якогось специфічного класу і не реалізує жодних службових інтерфейсів понад ті, які потрібні для бізнес-моделі. Тобто POJO клас - це просто клас без особливих вимог. Єдина вимога - відсутність різних наворотів, зав'язаних на певному фреймворку. Як правило, такі класи не успадковують від інших класів (крім класів POJO з того ж пакета), не реалізують інтерфейсів — іноді робиться виняток для маркерних інтерфейсів зі стандартної бібліотеки типу Serializable або Cloneable — не використовують анотацій і не залежать від сторонніх бібліотек. Але зазначу, що уPOJO можуть бути і методи з бізнес-логікою, і довільні конструктори. Якщо дозволити анотації, які не вносять зміни до семантики класу (без яких призначення об'єкта та логіка його роботи не зміняться), до POJO також можна віднести Entity сутності JPA та об'єкти DTO , які десеріалізуються з XML або JSON , правила для яких задані в анотаціях. Також для POJO класів бажано перевизначити equals та hashCode , адже це може допомогти їм краще виконувати свою роль. Приклад POJO класу:
public class User {
   private Long id;
   private String firstName;
   private String lastName;
   private Long age;

   public User(final Long id, final String firstName, final String lastName, final long age) {
       this.id = id;
       this.firstName = firstName;
       this.lastName = lastName;
       this.age = age;
   }

   public Long getId() {
       return this.id;
   }

   public String getFirstName() {
       return this.firstName;
   }

   public String getLastName() {
       return this.lastName;
   }

   public Long getAge() {
       return this.age;
   }

   @Override
   public boolean equals(final Object o) {
       if (this == o) return true;
       if (o == null || this.getClass() != o.getClass()) return false;
       final User user = (User) o;
       return Objects.equals(this.id, user.id) &&
               Objects.equals(this.firstName, user.firstName) &&
               Objects.equals(this.lastName, user.lastName) &&
               Objects.equals(this.age, user.age);
   }

   @Override
   public int hashCode() {
       return Objects.hash(this.id, this.firstName, this.lastName, this.age);
   }
}

26. Які елементи можуть містити клас?

Клас може містити такі елементи:
  • поля класу;
  • статичні поля класу;
  • блок ініціалізації;
  • статичний блок ініціалізації;
  • конструктори (порожній завжди визначений за умовчанням);
  • методи;
  • статичні методи;
  • різні інструкції (які можуть висіти над самим класом або його складовими);
  • дженерики ;
  • успадкування від інших класів ( extends ) або імплементації від інтерфейсів ( implements ).

27. Розкажіть про успадкування Java. Які особливості використання ключового слова super?

Вище я вже розповів про успадкування та ключове слово super у Java. Згадаю ще кілька важливих моментів:
  1. Можливе успадкування лише одного класу: множинне успадкування у Java відсутнє (але з появою дефолтних методів у Java 8 це твердження стане дуже спірним).
  2. Приватні методи та поля успадковуються теж, просто до них не буде доступу зі спадкоємця (але якщо у нас, наприклад, приватне поле і до нього є public або protected гетери та сеттери, з полем можна працювати через них).
  3. final класи не успадковуються.
  4. final методи не перевизначаються (але їх можна успадковувати та перевантажувати).
  5. static методи та змінні не успадковуються (т. до. вони прив'язані не до об'єктів, а до класів).
  6. При успадкування від абстрактних класів, обов'язкова реалізація їх абстрактних методів, чи поточний клас теж треба оголосити абстрактним.
  7. За наявності не дефолтних конструкторів у батьків, у класі нащадка їх обов'язково потрібно перевизначати (але @Override над ними не пишеться).
  8. Перевизначеним методам у спадкоємці можна розширювати модифікатор доступу: private -> default -> protected -> public .
  9. Перевизначеним методам у спадкоємці можна звужувати виключення, що прописуються, наприклад: Exception -> IOException -> FileNotFoundException.
Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 3 – 5

28. Що таке сигнатура методу? Наведіть приклади правильних та неправильних сигнатур

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