JavaRush /Java блог /Random UA /Кава-брейк #98. Новий виняток Nullpointer у Java 17. Що о...

Кава-брейк #98. Новий виняток Nullpointer у Java 17. Що означає у Java?

Стаття з групи Random UA

Новий виняток Nullpointer в Java 17

Джерело: Dev.to Кожному Java-розробнику варто знати про існування в Java 17 нового виключення Nullpointer Exception або NPE. Це одна з таких ситуацій, яку завжди потрібно намагатися запобігти. Іноді Nullpointer означає, що необхідно налагодити код, щоб знайти невелику помилку. Кава-брейк #98.  Новий виняток Nullpointer в Java 17. Що означає <T>  у Java?  - 1NPE - це виняток часу виконання, який виникає, коли ваш код хоче використовувати об'єкт або посилання на об'єкт, що має нульове значення. Воно може виникати, якщо не надано значення або об'єкт не має посилання. До останньої версії OpenJDK (версія 17) звичайний виняток Nullpointer у трасуванні стека виглядав приблизно так:
java.lang.NullPointerException: null
Звичайно, це далеко не все, що вам потрібно знати про трасування стека. Як бачите, тут не вказано, де і чому виник цей виняток. Подивіться, як із цією проблемою справляється Java 17:
Exception in thread "main" java.lang.NullPointerException:
Cannot assign field "i" because "a" is null
at Prog.main(Prog.java:5)
У цьому прикладі виняток вказує, де і яке наше посилання на нульовий об'єкт. Так просто!

Що означає <T> в Java?

Джерело: Dev.to <T> - це звичайна літера, що означає "Type", і вона відноситься до концепції Generic в Java. Ви можете використовувати для цього й іншу літеру, але, як можна помітити, літера T є кращою. Кава-брейк #98.  Новий виняток Nullpointer в Java 17. Що означає <T>  у Java?  - 2

Що таке Generic?

Generic – це спосіб параметризації класу, методу чи інтерфейсу. Давайте подивимося на приклад дженерика:
package Generics;

class House<T>{

    T doorNumber;

    public House(T doorNumber) {
        this.doorNumber = doorNumber;
    }

    public void print(){
        System.out.println("Your house number is: " + this.doorNumber);
    }
}
  • У нас є клас під назвою House , який може приймати довільний тип об'єкта.
  • Далі ми маємо поле з ім'ям doorNumber , яке також може приймати будь-який тип об'єкта.
  • Наприкінці ми оголошуємо параметризований конструктор та виводимо номер дверей.
Простіше кажучи, користувач може вирішити, чи це номер Integer, String, Float, і так далі. ПРИМІТКА: Ви можете використовувати лише Objects . Примітивні типи не підтримуються, оскільки дженерики призначені для використання під час компіляції. Коли ми використовуємо Generics, T замінює все, що може розширити клас Object , а примітивів немає цієї властивості. Припустимо, ми хочемо, щоб doorNumber був рядком.
public class GenericsExample {
    public static void main(String[] args) {
        House<String> mainHouse = new House<>("14a");
        mainHouse.print();

    }
}
Результат вийде таким:
Your house number is: 14a
Ми замінимо літеру "Т" на "String" і введемо номер будинку в конструктор. Ми можемо використовувати декілька типів, якщо, наприклад, нам потрібно, щоб клас приймав більше одного об'єкта. Можна додати ще одну літеру і цим сказати: ми хочемо, щоб клас прийняв інший Generic.
package Generics;

class House<T, V>{

    T doorNumber;
    V streetName;

    public House(T doorNumber, V streetName) {
        this.doorNumber = doorNumber;
        this.streetName = streetName;
    }

    public void print(){
        System.out.println("You live at: " + this.doorNumber + " " + this.streetName);
    }
}

public class GenericsExample {
    public static void main(String[] args) {
        House<Integer, String> mainHouse = new House<>(14, "Tellson Avenue");
        mainHouse.print();

    }
}
Результат буде таким:
You live at: 14 Tellson Avenue
Досі ми бачабо приклади використання Generic на рівні класу. Але у нас також можуть бути спільні методи та інтерфейси.

Метод Generic

package Generics;

class House{

    public <T> void print(T doorNumber){
        System.out.println("You live at house number: " + doorNumber);
    }

}

public class GenericsExample {
    public static void main(String[] args) {
        House mainHouse = new House();
        mainHouse.<Integer>print(14);

    }
}
Метод приймає будь-який тип об'єкта та виводить номер дверей, який буде будь-яким типом Object . І тут хочемо, щоб метод приймав ціле число. Результат буде:
You live at house Номер: 14

Інтерфейс Generic

Спочатку створіть інтерфейс.
package Generics;

interface Property<T>{
    void hasBalcony(T balcony);
}
Потім реалізуйте інтерфейс.
package Generics;

public class House implements Property<String> {

    @Override
    public void hasBalcony(String balcony) {
        System.out.println("Is there a balcony in the room? " + balcony);
    }

    public static void main(String[] args) {
        House mainHouse = new House();
        mainHouse.hasBalcony("YES");
    }

}
Результат:
Is there a balcony in the room? YES
Які переваги використання дженериків?
  1. Найкраща перевірка під час компіляції : якщо ви використовуєте тип об'єкта, відмінний від того, який ви вказали, компілятор повідомить вас про це.
  2. Можливість повторного використання : ви можете використовувати клас, метод або інтерфейс кілька разів, тому що ви вирішуєте, який тип об'єкта застосовувати в залежності від того, чого ви намагаєтесь досягти.
  3. Він відмінно підходить для структур даних та алгоритмів : ArrayList і HashMap – це лише кілька прикладів, де використовується Generic.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ