JavaRush/Java блог/Random UA/Кава-брейк #134. Чого слід уникати під час написання Java...

Кава-брейк #134. Чого слід уникати під час написання Java-коду. Як у Java використовуються final, finally та finalize

Стаття з групи Random UA
учасників

Чого слід уникати під час написання Java-коду

Джерело: Medium Вашій увазі пропонується стаття з перерахуванням поширених помилок, які розробники припускаються при написанні Java-коду. Кава-брейк #134.  Чого слід уникати під час написання Java-коду.  Як у Java використовуються final, finally та finalize - 1

Використання Enum.values

Те, що це вважається помилкою, застав мене зненацька, оскільки я регулярно використовував Enum.values ​​. Проблема тут полягає в тому, що Enum.values() за специфікацією має бути незмінним списком. Для цього він повинен повертати новий екземпляр масиву зі значеннями перерахування кожного виклику.
public enum Fruits {
    APPLE, PEAR, ORANGE, BANANA;

    public static void main(String[] args) {
        System.out.println(Fruits.values());
        System.out.println(Fruits.values());
    }
}
// output
// [Lcom.test.Fruits;@7ad041f3
// [Lcom.test.Fruits;@251a69d7
Тут два окремих об'єкти у пам'яті, тому може здатися, що це не має великого значення. Але якщо ви використовуєте Fruit.values() при обробці запиту і ви маєте високе навантаження, то це може призвести до проблем з пам'яттю. Ви можете легко виправити ситуацію, ввівши приватну статичну кінцеву змінну VALUES для кешування.

Передача параметрів Optional як параметр методу

Розглянемо наступний код:
LocalDateTime getCurrentTime(Optional<ZoneId> zoneId) {
    return zoneId.stream()
        .map(LocalDateTime::now)
        .findFirst()
        .orElse(LocalDateTime.now(ZoneId.systemDefault()));
}
Ми передаємо Optional параметр zoneId і на підставі його наявності вирішуємо, чи давати час у системному часовому поясі чи використовувати вказаний пояс. Однак це не зовсім правильний спосіб роботи з Optional. Ми повинні уникати їх використання як параметр і замість цього використовувати навантаження методів.
LocalDateTime getCurrentTime(ZoneId zoneId) {
  return LocalDateTime.now(zoneId);
}

LocalDateTime getCurrentTime() {
  return getCurrentTime(ZoneId.systemDefault());
}
Код, який ви бачите вище, набагато легше читати та налагоджувати.

Використання StringBuilder

Рядки в Java незмінні. Це означає, що після створення вони не редагуються. JVM підтримує пул рядків і перед створенням нового методу String.intern() , який повертає екземпляр з пулу рядків, відповідний значенню, якщо такий існує. Допустимо, ми хочемо створити довгий рядок, об'єднавши в нього елементи.
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
Нещодавно нам сказали, що це дуже погана ідея, тому що старі версії Java робабо таке:
  • у рядку 1 рядок “start” вставляється у пул рядків і неї указує longString
  • у рядку 2 до пула додається рядок “startmiddle” і на неї вказує longString
  • у рядку 3 у нас є “startmiddlemiddle”
  • у рядку 4 - "startmiddlemiddlemiddle"
  • і, нарешті, у рядку 5 ми додаємо в пул “startmiddlemiddlemiddleend” та вказуємо на нього longString
Всі ці рядки залишаються в пулі і ніколи не використовуються, що призводить до втрати великого обсягу оперативної пам'яті. Щоб уникнути цього, ми можемо використовувати StringBuilder.
String longString = new StringBuilder()
  .append("start")
  .append("middle")
  .append("middle")
  .append("middle")
  .append("end")
  .toString();
StringBuilder створює лише один рядок при виклику методу toString , тим самим позбавляючи нас від усіх проміжних рядків, які спочатку додані в пул. Однак після Java 5 це робиться компілятором автоматично , тому краще використовувати конкатенацію рядків за допомогою +.

Використання примітивних обгорток (primitive wrappers), коли вони не потрібні

Розглянемо такі два фрагменти:
int sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
Integer sum = 0;
for (int i = 0; i < 1000 * 1000; i++) {
  sum += i;
}
System.out.println(sum);
Перший приклад виконується на моєму комп'ютері в шість разів швидше за другий. Єдина відмінність полягає в тому, що ми використовуємо клас-обгортку Integer. Суть роботи Integer полягає в тому, що в рядку 3 середа виконання повинна перетворити змінну суми на примітивне ціле (автоматичне розпакування), і після виконання додавання результат потім упаковується в новий клас Integer. (Автоматична упаковка). Це означає, що ми створюємо 1 мільйон класів Integer та виконуємо два мільйони операцій упаковки, що пояснює різке уповільнення. Класи-обертки слід використовувати тільки тоді, коли їх потрібно зберігати в колекціях. Однак майбутні версії Java підтримуватимуть колекції примітивних типів, що зробить обгортки застарілими.

Як у Java використовуються final, finally та finalize

Джерело: Newsshare У цій статті ви дізнаєтеся, де, коли і навіщо використовується ключове слово Finalize, і чи варто його взагалі застосовувати у Java. Також ви дізнаєтеся про відмінності між final, finally та finalize.

Де використається блок finally?

Блок finally Java використовується для розміщення таких важливих частин коду, як код очищення, закриття файлу або, наприклад, закриття connection. Блок finally виконується незалежно від цього , чи з'являється виняток і обробляється це виняток. A finally містить усі важливі оператори незалежно від того, чи сталося виняток чи ні.

Як ви завершуєте (finalize) змінну Java?

Є 3 способи ініціалізувати кінцеву (final) змінну Java:
  • Ви можете ініціалізувати кінцеву змінну, коли її оголошено. Цей підхід є найпоширенішим.
  • Порожня кінцева змінна ініціалізується в блоці екземпляра-ініціалізатора або конструктора.
  • Порожня кінцева статична змінна ініціалізується усередині статичного блоку.

Чи можемо ми викликати метод finalize вручну Java?

Метод finalize() не потрібний і не рекомендується викликати при виході об'єкта з області дії. Оскільки заздалегідь невідомо, коли (і взагалі) виконуватиметься метод finalize() . Загалом finalize – не найкращий метод для використання, якщо немає конкретної потреби у ньому. Починаючи з Java 9, він не рекомендується до використання.

Коли викликається метод finalize?

Метод finalize() викликається для очищення безпосередньо перед складання сміття.

У чому різниця між final, finally та finalize?

Основна відмінність між final, finally і finalize полягає в тому, що final це модифікатор доступу, finally блок в обробці винятків, а finalize метод класу об'єкта.

Чи можна перевизначити методи final?

Ні, методи, оголошені остаточними (final), неможливо знайти перевизначені чи приховані.

Чи можемо використовувати try без catch?

Так, можна мати блок try без блоку catch , використовуючи блок final . Як відомо, блок final завжди буде виконуватися, навіть якщо у блоці try виник будь-який виняток, крім System.

Що таке методи?

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

Чи може конструктор бути final?

Конструктори НІКОЛИ не можуть бути оголошені як final. Ваш компілятор завжди буде видавати помилку типу "модифікатор final не дозволено". Final при застосуванні до методів означає, що метод може бути перевизначений у підкласі. Конструктори не є звичайними методами.

Навіщо використовується ключове слово finally?

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

Яка взагалі користь finally?

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

Чому метод Finalize захищений?

Чому модифікатор доступу методу finalize() зроблений захищеним? Чому не може бути публічним? Він не є публічним, тому що його не повинен викликати будь-хто, крім JVM. При цьому він повинен бути захищеним, щоб його могли перевизначити підкласи, яким необхідно визначити для нього поведінку.

Чи завжди метод finalize викликається у Java?

Метод finalize викликається, коли об'єкт має зібрати сміття. Це може статися будь-коли після того, як він став придатним для складання сміття. Зверніть увагу: цілком можливо, що об'єкт ніколи не піддається складання сміття (і, отже, finalize ніколи не викликається).

У чому різниця між throw та throws?

Ключове слово throw використовується для спеціального виключення. Ключове слово throws використовується для оголошення одного або декількох винятків, розділених комами. При використанні throw створюється лише один виняток.

У чому різниця між ключовими словами try catch та finally?

Це два різних поняття: блок catch виконується тільки в тому випадку, якщо у блоці try виникає виняток. Блок finally завжди виконується після блоку try(-catch), незалежно від того, з'явився виняток чи ні.

Чи можемо ми використовувати finally без try Java?

Блок finally повинен бути пов'язаний із блоком try, ви не можете використовувати finally без блоку try. Ви повинні помістити в цей блок оператори, які повинні виконуватися завжди.

Чи можемо ми успадкувати метод final?

Чи успадковується метод final? Так, метод final успадковується, але ви не можете його перевизначити.

Який метод не можна перевизначити?

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

Що станеться, якщо метод final буде перевизначено?

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

Ключове слово final та метод finalize працюють однаково?

У їхніх функціях немає подібності, крім подібних назв. Ключове слово final може використовуватися з класом, методом або змінною Java. Клас final не розширюється в Java, метод final не може бути перевизначений, а змінна final не може бути змінена.

Що таке ключове слово super в Java?

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

У чому різниця між ключовими словами static та final?

Основна різниця між ключовими словами static та final полягає в тому, що ключове слово static використовується для визначення члена класу, який можна використовувати незалежно від будь-якого об'єкта цього класу. Ключове слово Final використовується для оголошення постійної змінної, а також методу, який не можна перевизначити, та класу, який не можна успадковувати.
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.