JavaRush/Курси/Java Syntax Zero/Особливості об'єктів у мові Java

Особливості об'єктів у мові Java

Відкрита

1. Властивості: гетер і сетер

Коли великий проєкт розробляють десятки програмістів одночасно, нерідко виникають проблеми з тим, що програмісти по-різному поводяться з даними, які зберігаються в полях класу.

Ніхто докладно не вивчає документацію щодо класів, або в ній може бути описано не всі випадки, тому часто трапляються ситуації, коли дані всередині об'єкта «псуються» і об'єкт стає неприпустимим.

Щоб уникнути таких ситуацій, у Java прийнято всі поля класу робити приватними (private). Тільки методи класу можуть змінювати змінні класу, і ніякі методи з інших класів не мають безпосереднього доступу до змінних класу. Отак.

Якщо ви хочете, щоб інші класи могли отримувати або змінювати дані всередині об'єктів вашого класу, потрібно додати в код вашого класу два методи — get-метод і set-метод. Приклад:

Код Примітка
class Person
{
   private String name;

   public Person(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}


private-поле name



Ініціалізація поля за допомогою конструктора


getName() — метод повертає значення поля name




setName() — метод змінює значення поля name

Жоден інший клас не зможе безпосередньо змінити значення поля name. Якщо комусь потрібно отримати значення поля name, доведеться викликати метод getName() для об'єкта типу Person. Якщо хочеться поміняти в коді значення поля name, потрібно буде викликати метод setName() для об'єкта типу Person.

Метод getName() інакше називають «гетер поля name», а  метод setName() — «сетер поля name».

Це дуже поширений підхід. У 80–90 % всього Java-коду ви ніколи не побачите публічних змінних класу. Натомість вони будуть оголошені private (або protected), і кожна змінна матиме публічні гетери й сетери.

З таким підходом код стає довшим, але надійнішим.

Безпосереднє звернення до змінної класу — це як поворот через подвійну суцільну лінію: простіше та швидше, але якщо так робитимуть усі, то всім буде від цього тільки гірше.

Припустімо, ви хочете створити клас, який описує точку з координатами x і y на площині. Отак це зробив би програміст-початківець:

class Point
{
   public int x;
   public int y;
}

А отак це зробив би досвідчений Java-програміст:

Код
class Point {
 private int x;
 private int y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y;
   }
}

Код став довшим? Безумовно.

Натомість у сетери й гетери можна додати валідацію параметрів. Наприклад, можна слідкувати за тим, щоб x та y завжди були більшими за нуль (або не меншими за нуль). Приклад:

Код Примітка
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x < 0 ? 0 : x;
      this.y = y < 0 ? 0 : y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x < 0 ?  0 : x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y < 0 ? 0 : y;
   }
}

11
Задача
Java Syntax Zero,  11 рівень4 лекція
Недоступна
Чи з дахом, чи без нього — от питання
Ти зробив попереднє замовлення на новеньку Bugatti рівно пів року тому. Зараз червень, саме час їздити на кабріолеті. Але ти забув, який тип кузова вибрав під час замовлення. Твоє завдання — додати функціональність для отримання поточної конфігурації та для її зміни в разі потреби. Для цього створи
11
Задача
Java Syntax Zero,  11 рівень4 лекція
Недоступна
Зарплата
У нас є клас Programmer, а в ньому є дуже важливе поле — salary. Наше завдання таке: треба додати можливість отримати й змінити значення цього поля за допомогою гетера й сетера. Але є нюанс: зарплату можна тільки підвищувати. Отож тобі потрібно додати в сетер перевірку: якщо значення аргументу більш

2. Тривалість життя об'єкта

Ви вже знаєте, що об'єкти створюють за допомогою оператора new, а от як їх видаляють? Не існують же вони вічно — для цього ніякої пам'яті не вистачить.

У багатьох мовах програмування, як-от у С++, для видалення об'єкта є спеціальний оператор delete. А як вирішується це питання в Java?

У мові Java все влаштовано трохи по-іншому, і оператора delete у Java немає. Чи означає це, що об'єкти в Java не видаляються? Ні, звичайно ж, видаляються. Інакше в Java-програмах швидко закінчилася би пам'ять, і про місяці безперервної роботи навіть і не йшлося б.

У мові Java процес видалення об'єктів повністю автоматизовано — видаленням об'єктів займається сама Java-машина. Такий процес називають збиранням сміття (garbage collecting), а механізм, який збирає сміття, — збирачем сміттяGarbage Collector або скорочено GC.

Тож як Java-машина дізнається, що якийсь об'єкт потрібно видалити й коли?

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

У Java не можна взяти й створити посилання на наявний об'єкт: його можна тільки присвоїти. Якщо ми видалили всі посилання на об'єкт, його втрачено назавжди.

Циклічні посилання

Описана вище логіка звучить чудово, доки ми не придумаємо простий контрприклад: у нас є два об'єкти, що посилаються один на одного (зберігають посилання один на одного). Більше ніхто жодного посилання на ці об'єкти не зберігає.

До цих об'єктів не можна звернутися з іншого коду, проте посилання на них усе ж таки існують.

Саме тому збирач сміття розділяє об'єкти не на «об'єкти з посиланнями» і «об'єкти без посилань», а на досяжні й недосяжні.

Досяжні об'єкти

Спочатку до списку досяжних додаються об'єкти, які на 100 % «живі». Наприклад, поточна нитка (Thread.current()) або Консоль (System.in).

Відтак список досяжних об'єктів поповнюють ті, на які посилаються перші досяжні об'єкти. Потім ті, на які посилаються другі і т. д.

Отже, якщо є якась група об'єктів, що посилаються тільки один на одного, але досяжні об'єкти до них жодним чином дістатися не можуть, такі об'єкти будуть вважатися сміттям і будуть видалені.


3. Збирання сміття

Фрагментація пам'яті

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

І запросто може трапитися ситуація, коли ми не зможемо створити великий об'єкт (наприклад, масив на мільйон елементів) через відсутність великого шматка вільної пам'яті. Тобто вільна пам'ять нібито і є, і її багато, а от великого цільного шматка вільної пам'яті може й не бути.

Оптимізація (дефрагментація) пам'яті

Java-машина вирішує цю проблему специфічним чином. Приблизно отак:

Пам'ять розділяється на дві частини. Усі об'єкти створюються (і видаляються) лише в одній її половині. Коли настає час усунути «дірки» в пам'яті, всі об'єкти з першої половини копіюються у другу половину. Однак копіюються вони вже впритул один до одного, щоб «дірок» не було.

Цей процес має приблизно такий вигляд:

Етап 1: Після створення об'єктів

Збирання сміття в Java

Етап 2: Виникнення «дірок»

Збирання сміття в Java

Етап 3: Усунення «дірок»

Збирання сміття в Java

Таким чином, навіть не потрібно видаляти об'єкти. Java-машина просто копіює всі досяжні об'єкти в нове місце, а всю ділянку пам'яті зі старими об'єктами оголошує вільною.

Коментарі (14)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
24 лютого 2024, 17:03
Могли бы преподователи написать, что в getName() и setName() "Name" - это назание переменной, но только с большой буквы ?! Как это потом используется в задачах. В лекции это неочевидно написано, а я тыкал повсюду именно такое написание методов, а мне все "неправильно!!!" в ответ. Пишите, что getName(), где Name - это назание переменной с большой буквы в сносках и ВСЁ!!! Может это и не так я понял, но в задачах именно такая логика.
Ва Дим
Рівень 28
2 квітня 2024, 11:57
але там же приклажи є.Якщо перший не дає відповіді то в прикладі з х і у вже видно
2 квітня 2024, 17:03
Здогадуватись та знати (з лекції) - різні слова.
Василь trainee в Kindgeek
27 серпня 2023, 18:18
там де треба прописати гетер або сетер, то в Intelliage IDEA можна натиснути Alt + Insert і вибрати вставку гетера, сетера або обидва для потрібних полів.
Олег
Рівень 111
Expert
16 квітня 2023, 19:47
Щось до цієї лекції мало коментарів) Мабуть це той рівень на якому вирішують продовжувати навчання. Не все так складно)
Valentyna
Рівень 30
11 січня 2024, 20:10
Теж на це звернула увагу. Ви, бачу, все ж продовжили навчання.
Олег
Рівень 111
Expert
16 січня 2024, 12:24
Так з великими тормозами але продовжую ) Все ж хочу опанувати цю справу.
30 червня 2024, 21:51
і як воно? Ще продовжуєте?
Олег
Рівень 111
Expert
20 липня 2024, 06:07
Продовжую! Мало що розумію але продовжую )))
Vlad
Рівень 21
26 вересня 2024, 17:10
111 рівень, машина 💪 До якого я дійду, цікаво...
kalkulator¹
Рівень 51
7 листопада 2022, 16:25
/* Comment has been deleted */
Beisik
Рівень 25
9 листопада 2022, 16:00
Ну так в умові так написано)
Roma Chernesh
Рівень 16
7 січня 2023, 01:00
у якій задачі?
Lipovskyi Volodymyr
Рівень 36
16 травня 2022, 17:44
Так вон для чого потрібна дефрагментація)))