Нульовий вказівник

Нульовий (порожній) вказівник (рідше — покажчик) — вказівник, який нікуди не вказує. Використовується для того, щоб показати, що дана змінна-вказівник ні на що не посилається. У різних мовах програмування представлений різними константами, наприклад:

Тоні Гоар, який винайшов нульовий вказівник у 1965 році, вважає це помилкою, яка імовірно коштувала мільярди доларів, оскільки спроба розіменування нульового вказівника зазвичай приводить до збою й припинення роботи програми[1].

Особливості використання в різних мовах

C та C++

Макрос NULL визначено у файлі <stddef.h>.

ANSI C гарантує, що значення NULL еквівалентне 0, тому записи

  int *a, *b; 
  a = NULL;
  b = 0;

еквівалентні — вказівники a та b отримають однакове значення.

На відміну від C в Паскалі, який є дуже суворим щодо типів, Nil в жодному випадку не еквівалентний числу 0.

Java

Докладніше: Java

Мова програмування Java використовує null для позначення порожнього посилання. Також мова визначає так званий тип даних null. При спробі використання null замість реального об'єкта віртуальна машина створює виняткову подію типу java.lang.NullPointerException. Зокрема, ця подія виникає при:

  • виклику динамічного метода об'єкта null.
  • доступі або зміні поля об'єкта null.
  • обчисленні довжини об'єкта null наче він є масивом.
  • доступі або зміні комірок об'єкта null наче він є масивом.
  • створенні виняткової ситуації з об'єктом null замість об'єкта типу Throwable.

Додатки також можуть створювати виняткові ситуації типу NullPointerException за інших невірних використаннях об'єктів типу null[2].

З огляду на численні проблеми, спричинені неправильною обробкою об'єктів null та досвіду використання деяких інших мов програмування в бібліотеці стандартних класів Java SE 8 версії був доданий контейнер Optional<T>. Об'єкти даного класу можуть містити значення типу null. Якщо контейнер містить непорожнє значення, тоді метод isPresent() поверне true а метод get() поверне це значення. Також цей контейнер пропонує низку додаткових методів, поведінка яких залежить від наявності непорожнього значення. Наприклад, метод orElse() повертає значення за замовченням при відсутності даних в контейнері, ifPresent() виконує блок коду за умови наявності даних в контейнері[3].

Наприклад, якщо комп'ютер не має звукової карти і метод getSoundcard() повертає null, то при виконанні наступного коду:

String version = computer.getSoundcard().getUSB().getVersion();

виникне виняткова ситуація типу NullPointerException при спробі викликати метод getUSB(). Проте, засобами контейнеру Optional<T> цей код може бути перетворений на безпечніший (після відповідного рефакторингу залучених типів даних):

String version = computer.flatMap(Computer::getSoundcard)
                   .flatMap(Soundcard::getUSB)
                   .map(USB::getVersion)
                   .orElse("UNKNOWN");

унаслідок виконання якого змінна version матиме значення «UNKNOWN» за відсутності звукової карти[4].

Примітки

  1. Tony Hoare. Null References: The Billion Dollar Mistake. Архів оригіналу за 19 січня 2009. Процитовано 23 жовтня 2010.
  2. Class NullPointerException. Java™ Platform Standard Ed. 8. API Specification. Oracle. 2016.
  3. Class Optional<T>. Java™ Platform Standard Ed. 8. API Specification. Oracle. 2016.
  4. Raoul-Gabriel Urma (March 2014). Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional!. Oracle Technology Network.

Див. також

Посилання