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

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

Стаття з групи Random UA
Hello, Hello! Сьогодні Java-розробники дуже потрібні. Забезпечити вакансією я вас, звичайно, не можу, але трохи допомогти в тому, щоб ви набули нових знань і закрабо деякі прогалини, спробую. Тож продовжуємо розбір 250+ питань із співбесід на Java-розробника. Посилання на попередні частини розбору – наприкінці статті.Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 1

39. Що таке модифікатори доступу Java? Назвіть їх. Навіщо вони використовуються?

Раніше я вже описував модифікатори доступу в питанні про елементи Java, які відповідають за інкапсуляцію. Але все ж таки нагадаю. Модифікатори доступу Java — це ключові слова, які описують рівень доступу, що надається, до певного компонента Java. Модифікатори доступу можуть бути:
  • public — елемент із цим модифікатором буде загальнодоступним. Тобто. поля та методи, класи, оголошені з модифікатором public, видно іншим класам як з поточного пакета, так і зовнішніх пакетів;
  • protected — елемент з даним модифікатором буде доступний з будь-якого місця в поточному класі поточного пакета або класах спадкоємців, навіть якщо вони знаходяться в інших пакетах;
  • default , або відсутній модифікатор - цей модифікатор використовується неявно, коли модифікатор доступу зовсім не вказується. Він схожий на попередній, крім допустимості видимості у класах-спадкоємцях, які знаходяться в інших пакетах;
  • private — найзакритіший із усіх модифікаторів, який допускає доступ до елемента лише в межах поточного класу.
Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 2

40. Назвіть основну особливість статичних та змінних методів

Дуже дивне формулювання - "змінні методи". Напевно, тут маються на увазі звичайні, нестатичні методи. Так от, основна різниця в тому, що статичні методи належать класу і, власне, для них не потрібно створювати екземпляр цього класу: його можна викликати лише використовуючи тип класу. Наприклад, у нас є статичний метод, щоб погладити кота:
public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Погладить кота - " + cat.getName());
   }
Для його виклику нам не потрібен екземпляр класу CatService :
Cat cat = new Cat(7, "Bobi");
CatService.petTheCat(cat);
У той час, як звичайні методи прив'язані (належать) об'єкту, і щоб їх викликати, необхідно мати екземпляр (об'єкт), у якого і буде викликаний метод. Наприклад, у кота є нестатичний метод — м'яукати:
class Cat {
   public void mew() {
       System.out.println("Meow! Meow! Meow!");
   }
Для виклику цього методу нам знадобиться конкретний екземпляр кота:
Cat cat = new Cat(7, "Bobi");
cat.mew();

41. Які основні обмеження діють на статичні та “змінні” методи?

Як я і сказав раніше, основне обмеження звичайного методу в тому, що завжди має бути деякий екземпляр, у якого цей метод буде викликаний. А ось статичний метод цього не вимагає, але він і не може посилатися на посилання this - на елементи поточного об'єкта - оскільки поточного об'єкта для нього не існує.

42. Що означає ключове слово static? Чи може статичне метод бути перевизначений чи перевантажений?

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

43. Чи може бути статичним і абстрактним одночасно?

У попередній статті я вже згадував: метод не може бути абстрактним і статичним одночасно. Абстрактність методу має на увазі, що він має бути перевизначений у спадкоємці. У той же час статичний метод належить класу, і його не можна перевизначити: це викликає протиріччя, яке побачить компілятор і почне лаятись. Якщо у вас виникла така ситуація, варто всерйоз задуматися про правильність побудови архітектури вашої програми (адже з нею щось не так).Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 3

44. Чи можна використовувати статичні методи у середині звичайних? Навпаки? Чому?

Статичні методи можна використовувати у звичайних, тому що цьому нічого не перешкоджає. У той самий час зворотна ситуація неможлива: статичний метод неспроможна використовувати звичайний метод, які мають посилання конкретний екземпляр даного класу. А як ми пам'ятаємо, для статичних членів класу посилання this недоступне: конкретних об'єктів класу може бути скільки завгодно, і у кожного з них буде посилання на самого себе — this . І як тоді зрозуміти, яке саме посилання це потрібно взяти? А ніяк. Тому й статичні елементи що неспроможні посилатися на нестатичні, без посилання конкретний об'єкт. Власне, статичний метод може використовувати не статичний тільки якщо має посилання на конкретний об'єкт. Наприклад ту, яка прийшла як аргумент:
public static void petTheCat(Cat cat) {
   System.out.println("Погладить кота - " + cat.getName());
}
Тут бачимо, що у статичному методі petTheCat викликається звичайний, нестатичний метод об'єкта Cat - getName .

45. Що таке interface? Чи може бути final interface?

Як ми пам'ятаємо, Java не має множинного успадкування. Інтерфейси — це щось подібне до його альтернативи. Інтерфейс нагадує дуже урізаний клас. Вони визначають функціонал без конкретної реалізації, який реалізують класи, що імплементують ці інтерфейси. Приклад інтерфейсу:
public interface Animal {
    void voice();
}
Приклад реалізації інтерфейсу класом:
class Cat implements Animal {

   @Override
   public void voice() {
       System.out.println("Meow! Meow! Meow!");
   }
}
Головне, що потрібно знати про використання інтерфейсів:
  1. Методи інтерфейсу мають лише заголовок, без конкретного тіла методу, тобто. мають бути абстрактними (але без застосування ключового слова abstract ). Виняток із цього — статичні та дефолтні методи, для яких необхідно мати тіло методу.
  2. Клас може реалізовувати безліч інтерфейсів (як і говорив, це альтернатива множинному успадкування), які прописуються через кому: class Lion implements Animal, Wild .
  3. Інтерфейси створюються за допомогою ключового слова - interface .
  4. При реалізації інтерфейсу класом використовується ключове слово - implements .
  5. Клас, який реалізує певний інтерфейс, повинен реалізувати всі його абстрактні методи, або повинен оголосити себе абстрактним.
  6. Основна мета використання інтерфейсів - реалізація поліморфізму (здатність об'єктів набувати безліч форм).
  7. В інтерфейсі, як правило, не пишуть модифікатори доступу для методів: вони за замовчуванням public , інші модифікатори, відмінні від public , задавати не можна. Починаючи з Java 9, можна використовувати private модифікатори для методів.
  8. Змінні інтерфейси за промовчанням static final , інакше кажучи - константи: їх завжди потрібно проініціалізувати безпосередньо в інтерфейсі.
  9. Неможливо створити об'єкт інтерфейсу.
Відповідь на запитання, чи можуть бути інтерфейси фінальними, звичайно ж, ні. Адже сама сутність інтерфейсів у тому, щоб їх реалізовували. А як ми всі чудово пам'ятаємо, final на рівні класу робить його не успадкованим, і у випадку з інтерфейсом не реалізовується. А навіщо нам інтерфейс, який не можна реалізувати та використати? Правильно — нема чого! І компілятор так вважає)) Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 4Сенс хіба що з'явився із введенням статичних методів в інтерфейси з Java 8, але це не змінило того факту, що інтерфейс не може бути фінальним. Про інтерфейси я розповів дуже поверхово, т.к. це велика тема. Докладніше про це — у статтях про інтерфейси в Java та різниці між абстрактними класами та інтерфейсами .

46. ​​Де можна ініціалізувати статичні поля?

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

47. Що таке анонімні класи?

Анонімні класи — це класи, які не мають власного типу. Про що я? Коли ми говорабо про інтерфейси, я згадав, що не можна створити об'єкт інтерфейсу: можна створити об'єкт класу, який реалізує інтерфейс. А якщо ви не хочете реалізовувати інтерфейс в якомусь класі, але при цьому вам потрібен об'єкт типу інтерфейсу? І найімовірніше, це буде одиничний випадок використання даного об'єкта. І у вас немає потреби створювати повноцінний клас реалізацію. Як ви це зробите? Правильно! Через анонімний клас! Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 5Припустимо, у нас є деякий інтерфейс Animal :
public final interface Animal {
   public void voice();
}
Якщо ми хочемо створити екземпляр цього інтерфейсу через анонімний клас:
Animal cat = new Animal() {
   @Override
   public void voice() {
       System.out.println("Meow! Meow! Meow!");
   }
};
І далі ви можете спокійно використовувати даний об'єкт та його реалізований метод — voice. Тобто анонімний клас реалізує цей інтерфейс і всі його абстрактні методи прямо тут і зараз. Інакше нам не створити об'єкт інтерфейсу/абстрактного класу, оскільки є не реалізовані/абстрактні методи. Як я згадав, анонімні класи використовуються як для реалізації абстрактних методів інтерфейсу, а й реалізації абстрактних методів абстрактного класу. Даний підхід хороший для ситуацій, коли об'єкт використовується разово або дана реалізація методів потрібна лише один раз, і немає потреби створювати окремий клас, який реалізовуватиме необхідний абстрактний клас/інтерфейс. Але також зазначу, що використання анонімних класів - рідкісне явище в роботі: як правило перевага все ж таки віддається звичайним класам. Детальніше про анонімні класи можна почитати ось у цій статті.

48. Що таке примітивні класи?

Як на мене, це дуже дивне питання і, можливо, це таке питання-пастка, адже Java не має такого поняття як примітивні класи: хіба що є поняття примітивні типи, яке ми вже розглядали раніше. Як ми пам'ятаємо, в Java є 8 примітивних типів - byte , short , int , long , float , double , char , boolean .Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 6

49. Що таке клас «обгортка» (wrapper)?

Головна проблема використання примітивних типів в Java - це те, що вони все ж таки не класи, а Java - все ж таки ООП мову. Тобто програми, написані цією мовою, зводяться до взаємодії між об'єктами. Ну, а примітиви — це не об'єкти. Вони не мають методів, навіть стандартних від класу Object . Ну а якщо нам знадобилося використовувати примітив як ключ у Map ? Тоді потрібно викликати метод hashCode . Також там можна викликати метод equals. Що тоді? Моментів, де має бути саме клас, а не примітив, може бути дуже і дуже багато, що робить примітиви невикористовуваними та небажаними елементами у програмі, адже це руйнує саму ідею ОВП. Але не так погано, як здається. Адже Java має поняття обгортки примітивів. Кожен примітивний тип має клас-аналог:
  • byte -> Byte.class
  • short -> Short.class
  • int -> Integer.class
  • long -> Long.class
  • float -> Float.class
  • double -> Double.class
  • char -> Character.class
  • boolean -> Boolean.class
Це уявлення простих типів, але як повноцінних класів з купою різноманітних і функціональних методів. Для зручного використання цих класів ввели поняття autoboxing та unboxing. Autoboxing — автоматичне перетворення примітивного типу на клас-аналог за потреби (наприклад, int в Integer ). Unboxing - процес, зворотний попередньому: автоматичне перетворення класу-обгортки примітиву до примітивного типу (наприклад, Integer до int ). Завдяки введенню класів-обгорток примітивів та процесів autoboxing -а та unboxing -а, примітивні типи змогли стати повноцінними членами ООП мови – Java.Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 7Щоб ознайомитися з цією темою докладніше, наполегливо рекомендую почитати цю статтю .

50. Що таке Nested class? Коли він використається?

Nested class – внутрішній клас, який є членом іншого класу. У Java існує 4 види таких внутрішніх класів: 1. Внутрішній клас Цей вид класів оголошується у тілі іншого класу. Вкладений внутрішній клас може отримати доступ до будь-якого приватного поля або методу екземпляра зовнішнього класу. Як приклад, створимо зоопарк, у якому ми матимемо тварину — зебра:
public class Zoo {
   class Zebra {
       public void toFeed(String food) {
           System.out.println("Дать зебре - " + food);
       }
   }
}
Нічого складного, чи не так? Погляньмо на приклад створення об'єкта внутрішнього класу:
Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.toFeed("яблоко");
Як ви вже побачабо, обов'язково потрібно створювати об'єкт класу, що обрамляє, на основі посилання якого можна створити об'єкт внутрішнього класу. Також хотілося б відзначити, що вкладений внутрішній клас неспроможна мати у собі статичних методів чи статичних полів. Саме тому, що внутрішній клас неявно пов'язаний з об'єктом свого зовнішнього класу, і він не може оголошувати жодних статичних методів у собі. 2. Статичні вкладені класи Цей клас схожий на попередній, тільки у нього модифікатор доступу staticбіля оголошення класу. Так як у цього виду класів немає доступу до нестатичних полів зовнішнього класу, він більше нагадує статичну частину зовнішнього класу, ніж на внутрішній клас. При цьому дані класу мають доступ до всіх статичних членів зовнішнього класу, навіть до приватних. Приклад статичного вкладеного класу:
public class Zoo {
   static class Zebra {
       public void toFeed(String food) {
           System.out.println("Дать зебре - " + food);
       }
   }
}
Спосіб створення трохи відрізняється від попереднього:
Zoo.Zebra zebra = new Zoo.Zebra();
zebra.toFeed("яблоко");
Тут не потрібен об'єкт зовнішнього класу до створення об'єкта вкладеного статичного класу. Від зовнішнього класу нам потрібен лише його тип, щоб можна було знайти розташування вкладеного класу. 3. Локальні класи Локальні класи — це класи, оголошені всередині тіла методу, у своїй створення та використання об'єкта локального класу можливе виключно межах цього методу. Приклад:
public class Zoo {
   public void toFeed(String animal, String food) {
       switch(animal){
           case "зебра":
               class Zebra {
                   void toFeedZebra(String food) {
                       System.out.println("Дать зебре - " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.toFeedZebra(food);
               ...
Приклад використання:
Zoo zoo = new Zoo();
zoo.toFeed("зебра", "яблоко");
Не бачачи код методу toFeed , ви б і не запідозрабо про існування локального класу, чи не так? Локальний клас може бути static чи transient , але його можна помітити як abstract чи final (тільки АБО, оскільки використання цих двох модифікаторів призведе до конфлікту). 4. Анонімні класи Про анонімні класи ми вже говорабо вище, і як ви пам'ятаєте, їх можна створити із двох джерел – інтерфейси та класи. Причини використання Внутрішні статичні та не статичні класи використовують тому, що іноді краще вбудувати невеликі класи у загальніші і зберігати їх разом: так у них буде більш висока пов'язаність та загальна мета. Власне використання вкладених класів збільшує інкапсуляцію коду. Причиною вибору локальних класів може бути те, що цей клас використовується виключно в межах одного методу. Чи потрібно в такому разі розмазувати код за програмою? Ні. Але при цьому додам, що у своїй практиці жодного разу не бачив використання локальних класів, т.к. потреба у них дуже спірна. Ну а причиною використання анонімних класів може бути те, що конкретна реалізація інтерфейсу або абстрактного класу буде необхідна лише один раз, тому немає потреби створювати під це окремий, повноцінний клас із реалізацією.Розбір запитань та відповідей із співбесід на Java-розробника.  Частина 5 - 8Вивчити внутрішні класи докладніше вам допоможуть ця та ця статті.

51. Які модифікатори доступу можуть мати клас?

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