JavaRush/Java блог/Random UA/9 речей про NULL в Java
Sdu
17 рівень

9 речей про NULL в Java

Стаття з групи Random UA
учасників
Java та null нерозривно пов'язані. Чи існує Java-програміст, який не зустрічався з " null pointer exception " і це сумний факт. Навіть винахідник концепції "null" назвав її своєю помилкою на мільярд доларів, тоді навіщо Java підтримує її? null був тут довгий час, і я вважаю, творці Java знають, що він створює більше проблем, ніж вирішує, так чому ж вони все ще миряться з цим. І це дивує мене ще більше, тому що філософією Java було спростити речі, ось чому вони більше не пораються з покажчиками, перевантаженням операторів та множинним успадкуванням, але чому null?9 речей про NULL в Java - 1Ну, я дійсно не знаю відповіді на це питання, але, що я точно знаю, не має значення скільки б null критикувався Java-програмістами та open-source спільнотою, ми повинні жити з ним. Замість шкодувати, краще дізнатися більше і бути впевненим, що ми використовуємо null правильно.

Чому Ви повинні дізнатися про null в Java?

Тому що, якщо Ви не звернете уваги на null, будьте впевнені, Java змусить страждати від жахливого java.lang.NullPointerExceptionі Ви вивчите цей урок, але підете важчим шляхом. Написання стійкого до "падіння" коду - це мистецтво і Ваша команда, замовники та користувачі оцінять це. На мій досвід, одна з основних причин NullPointerExceptionце недолік знань про null в Java. Багато хто з Вас вже знайомий з null, інші зможу дізнатися деякі старі і нові речі про ключове слово null. Давайте повторимо або дізнаємося деякі важливі речі про null в Java.

Що є null в Java

Як я казав, null дуже-дуже важлива концепція у Java. Спочатку він був винайдений для позначення відсутності чогось, наприклад, відсутність користувача, ресурсу або чого завгодно, але вже протягом року спантеличив Java-програмістів безліччю null pointer exception. У цьому уроці, ми дізнаємося основні факти про ключове слово null в Java, вивчимо деякі прийоми як уникнути неприємностей з null pointer exceptionsі мінімізувати перевірки на null.
  1. Насамперед, null це ключове слово в Java, так само як public, staticабо final. Регістр враховується, Ви не можете писати null як Null або NULL, компілятор не розпізнає його і буде викинута помилка.

    Object obj = NULL; // Not Ok
    Object obj1 = null //Ok

    Найчастіше з цим зустрічаються програмісти, які перейшли з інших мов програмування, але при використанні сучасних IDE проблема стає незначною. У наші дні, IDE на кшталт Eclipse або NetBeans можуть виправляти цю помилку доки Ви набираєте код, але в епоху Notepad, Vim та Emacs, це була поширена проблема, яка могла з'їсти купу дорогоцінного часу.

  2. Так само, як кожен примітив має значення за умовчанням, наприклад, це int0, у boolean це false, null це значення за умовчанням будь-яких типів посилань, простіше кажучи, для всіх об'єктів. Так само, як при створенні логічної змінної її значення за замовчуванням дорівнює false, так і будь-які змінні посилання в Java за промовчанням дорівнюватимуть null. Це істинно для всіх типів змінних: змінної-члена або локальної змінної, змінної екземпляра або статичної змінної, крім того, компілятор лаятиметься, якщо Ви використовуєте локальну змінну, не проініціалізувавши її.

    private static Object myObj;
    public static void main(String args[]){
        System.out.println("What is value of myObjc : " + myObj);
    }
    What is value of myObjc : null

    Це істинно як для статичних, так і для не статичних об'єктів, як Ви можете бачити тут, я зробив myObjстатичним посиланням, так що я можу використовувати її безпосередньо в методі main, який є статичним методом і не дозволяє звертатися до нестатичних змінних зсередини.

  3. Незважаючи на поширену помилку, null це не об'єкт ( Object) і ні тип. Це просто спеціальне значення, яке може бути призначене будь-якому типу посилань, і Ви можете привести null до будь-якого типу, як показано нижче:

    String str = null; // null can be assigned to String
    Integer itr = null; // you can assign null to Integer also
    Double dbl = null; // null can also be assigned to Double
    String myStr = (String) null; // null can be type cast to String
    Integer myItr = (Integer) null; // it can also be type casted to Integer
    Double myDbl = (Double) null; // yes it's possible, no error

    Як Ви можете бачити, приведення null до будь-якого типу посилань пройде успішно як під час компіляції, так і під час виконання програми. На відміну від того, що багато хто з Вас, можливо, подумав, це не призведе до викидання NullPointerException.

  4. null може бути призначений тільки посилання типу, Ви не можете призначити null примітивної змінної на кшталт int, double, floatабо boolean. Компілятор висловить Вам своє невдоволення, якщо Ви зробите як показано нижче:

    int i = null; // type mismatch : cannot convert from null to int
    short s = null; // type mismatch : cannot convert from null to short
    byte b = null: // type mismatch : cannot convert from null to byte
    double d = null; //type mismatch : cannot convert from null to double
    
    Integer itr = null; // this is ok
    int j = itr; // this is also ok, but NullPointerException at runtime

    Як Ви можете бачити, коли ми безпосередньо привласнюємо null примітиву, то отримуємо помилку процесу компіляції, але якщо привласнити null об'єкту класу-обгортки, а потім привласнити цей об'єкт відповідному примітивному типу, компілятор не відреагує, але ми будемо винагороджені під час виконання null pointer exception. Це відбувається через авто упаковки ( autoboxing) в Java, і ми ще зустрінемося з ним у наступному пункті.

  5. Будь-який клас-обгортка зі значенням null буде викидати java.lang.NullPointerExceptionколи Java розпакує( unbox) його в примітивну змінну. Деякі програмісти роблять помилку припускаючи, що авто упаковка( autoboxing) подбає про конвертацію null у значення за промовчанням для відповідного примітивного типу, наприклад, 0 для int, false для booleanі т.д., але це не вірно, в чому можна переконатися нижче:

    Integer iAmNull = null;
    int i = iAmNull; // Remember - No Compilation Error

    Але коли Ви запустите цей фрагмент коду, в консолі Ви побачите

    Exception in thread "main" java.lang.NullPointerException

    Це часто відбувається при роботі з HashMapі Integer key. Виконання коду, показаного нижче, перерветься, як тільки Ви його запустите.

    import java.util.HashMap;
    import java.util.Map;
    /**
    * An example of Autoboxing and NullPointerExcpetion
    *
    * @author WINDOWS 8
    */
    public class Test {
        public static void main(String args[]) throws InterruptedException {
            Map numberAndCount = new HashMap<>();
            int[] numbers = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5};
            for(int i : numbers){
                int count = numberAndCount.get(i);
                numberAndCount.put(i, count++); // NullPointerException here
            }
        }
    }

    Output: Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:25)

    Цей код виглядає дуже простим та нешкідливим. Ви просто підраховуєте скільки разів кількість зустрічається в масиві, класична техніка знаходження дублікатів. Розробник бере попередню підраховану кількість, збільшує його на одиницю і вставляє назад у Map. Він міг би подумати, що авто-упаковка потурбується про перетворення Integerв int, як це робиться в момент виклику методу put(), але він забуває, що якщо для числа підрахунок ще не проводився, метод get()поверне з HashMapnull, не нуль, тому що значення за замовчуванням для Integer це null, а не 0, і авто-упаковка викине null pointer exceptionпри спробі конвертувати Integer у змінну int.

  6. Оператор instanceofповертатиме false якщо в якості параметра вказати будь-яку посилальну змінну зі значенням null або null сам по собі. Приклад:

    Integer iAmNull = null;
    if(iAmNull instanceof Integer){
        System.out.println("iAmNull is instance of Integer");
    }else{
        System.out.println("iAmNull is NOT an instance of Integer");
    }

    Output : iAmNull is NOT an instance of Integer

    Це важлива властивість оператора instanceof, яка робить його корисним для перевірки типів.

  7. Ви знаєте, що Ви не можете викликати нестатичний метод у змінної посилання зі значенням null, це викличе NullPointerException, але Ви можете не знати, що Ви можете викликати статичний метод у посилальної змінної зі значенням null. Т.к. статичні методи використовують статичне зв'язування, де вони викидають NullPointerException. Ось приклад:

    public class Testing {
        public static void main(String args[]){
            Testing myObject = null;
            myObject.iAmStaticMethod();
            myObject.iAmNonStaticMethod();
        }
        private static void iAmStaticMethod(){
            System.out.println("I am static method, can be called by null reference");
        }
        private void iAmNonStaticMethod(){
            System.out.println("I am NON static method, don't date to call me by null");
        }
    }

    Output: I am static method, can be called by null reference
    Exception in thread "main" java.lang.NullPointerException
    at Testing.main(Testing.java:11)
  8. Ви можете послати null як параметр методу, який приймає будь-який тип посилання, наприклад:

    public void print(Object obj)

    може бути викликаний як

    print(null)

    Це нормально з погляду компілятора, але подальша поведінка залежить від методу. Null-безпечний метод не викине NullPointerException, а просто коректно завершиться. Якщо бізнес-логіка дозволяє, рекомендується писати null-безпечні методи.

  9. Ви можете порівнювати null за допомогою операторів ==(рівно) і !=(не рівно), але не можете використовувати його з іншими арифметичними або логічними операторами, на кшталт <(менше) або >(більше). На відміну від SQL, Java null == nullповерне true, як показано нижче:

    public class Test {
    	public static void main(String args[]) throws InterruptedException {
    		String abc = null;
    		String cde = null;
    		if(abc == cde){
    			System.out.println("null == null is true in Java");
    		}
    		if(null != null){
    			System.out.println("null != null is false in Java");
    		}
    		// classical null check
    		if(abc == null){
    			// do something
    		}
    		// not ok, compile time error
    		if(abc > null){
    
    		}
    	}
    }

    Output:
    null == null is true in Java
Це все про null у Java. Напрацювавши деякий досвід у Java-програмуванні і використовуючи прості хитрощі, щоб уникнути NullPointerException, Ви зможете зробити Ваш код безпечним. Т.к. Значення null може розглядатися як порожнє або неініціалізоване значення, це часто є джерелом плутанини, ось чому так важливо документувати поведінку методу при вхідному значенні null. Завжди пам'ятайте, null це значення за замовчуванням змінних посилань, і Ви не можете викликати методи екземпляра або отримувати доступ до змінних екземпляра використовуючи null-посилання в Java.
Коментарі
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Для цієї сторінки немає коментарів.