Открыть сервис

Null

Null (от лат. nullus — никакой, ничто) — в программировании и информатике специальное значение, обозначающее отсутствие какого-либо объекта, данных или ссылки. Null указывает на то, что переменная, указатель или поле не содержит никакого осмысленного значения, находится в неопределённом состоянии или не инициализировано. В разных языках программирования null может быть представлен как отдельный тип данных (например, в Java), как специальное значение ссылочного типа (в C#) или как константа (в C/C++). Концепция null тесно связана с понятием «пустого» значения, но не тождественна ему: в отличие от пустой строки, нуля или пустого списка, null означает именно отсутствие ссылки на объект, а не наличие объекта с нулевым содержимым.

История

Концепция null была введена Тони Хоаром в 1965 году при разработке языка ALGOL W. Хоар ввёл нулевые ссылки (null references) для обозначения отсутствия значения в ссылочных типах данных. Позднее он назвал это изобретение «ошибкой на миллиард долларов», имея в виду огромное количество программных ошибок и уязвимостей, вызванных неправильной обработкой null (так называемые ошибки разыменования нулевого указателя — null pointer dereference). Несмотря на критику, null стал неотъемлемой частью большинства языков программирования, включая C, C++, Java, C#, JavaScript, Python и многие другие.

В 1970-х годах null был реализован в языке C как макрос NULL, определённый как (void*)0 или просто 0. В C++ null-указатель также представляется целочисленной константой 0, а с появлением стандарта C++11 — ключевым словом nullptr для строгой типизации. В языках с динамической типизацией (JavaScript, Python) null часто дополняется значением undefined (JavaScript) или None (Python), которые семантически близки, но имеют разные контексты использования.

Типы null в разных языках программирования

C и C++

В C и C++ null-указатель — это константа NULL (обычно (void*)0) или литерал 0. В C++11 появилось ключевое слово nullptr, которое имеет тип std::nullptr_t и неявно преобразуется в любой тип указателя. Использование NULL в C++ считается устаревшим, так как NULL может быть неявно преобразован в целочисленный тип, что приводит к неоднозначностям при перегрузке функций.

Java

В Java null — это специальное литеральное значение, которое может быть присвоено любой переменной ссылочного типа (объекту, массиву, строке). При попытке вызова метода или доступа к полю у объекта, равного null, возникает исключение NullPointerException. В Java нет примитивного типа null; null не является объектом и не имеет методов.

C#

В C# null — это значение по умолчанию для ссылочных типов. Начиная с C# 2.0, появились nullable-типы для значимых типов (например, int?), которые могут принимать null. В C# 8.0 введены nullable-ссылочные типы, позволяющие компилятору предупреждать о потенциальных разыменованиях null.

JavaScript

В JavaScript null — это примитивное значение, обозначающее «ничего», «пусто» или «неизвестное значение». Тип null в JavaScript — object (что является исторической ошибкой языка). Отдельно существует undefined, который обозначает отсутствие присвоенного значения. Различие: null обычно присваивается явно, а undefined — автоматически, когда переменная объявлена, но не инициализирована.

Python

В Python аналогом null является None — единственный объект типа NoneType. None используется для обозначения отсутствия значения. В Python нет отдельного null-указателя; None — это объект-синглтон, который можно сравнивать с помощью оператора is.

SQL

В базах данных NULL — это специальное значение (не равное ничему, даже самому себе), обозначающее отсутствие данных. В SQL NULL не участвует в обычных сравнениях: NULL = NULL возвращает не true, а UNKNOWN. Для проверки на NULL используются операторы IS NULL и IS NOT NULL. NULL в SQL может возникать при отсутствии значения в столбце, при внешних соединениях (OUTER JOIN) или при агрегации пустых наборов.

Проблемы, связанные с null

Ошибка разыменования нулевого указателя (Null Pointer Dereference)

Наиболее распространённая ошибка — попытка получить доступ к полю или вызвать метод у объекта, равного null. В языках со статической типизацией (Java, C#) это приводит к исключению времени выполнения; в C/C++ — к неопределённому поведению (часто — к аварийному завершению программы). По оценкам, ошибки, связанные с null, составляют значительную долю всех программных дефектов.

Неоднозначность семантики

Null может означать:

Эта неоднозначность часто приводит к путанице и необходимости дополнительных проверок.

Проблемы с производительностью

Частые проверки на null (if (x != null)) увеличивают объём кода и могут снижать производительность, особенно в критичных участках. В некоторых языках (Java, C#) компилятор генерирует проверки на null для каждого вызова виртуального метода, что также влияет на скорость.

Подходы к борьбе с null

Null-безопасные языки

Некоторые языки программирования полностью исключают null из системы типов, заменяя его опциональными типами (Option, Maybe). Примеры:

В этих языках компилятор заставляет программиста явно обрабатывать случай отсутствия значения, что практически исключает ошибки разыменования null.

Null-объект (Null Object Pattern)

Паттерн проектирования, при котором вместо null используется специальный объект-заглушка, реализующий тот же интерфейс, но с пустыми (безопасными) методами. Например, вместо null-ссылки на логгер используется NullLogger, который ничего не делает.

Optional и Maybe

В Java 8 появился класс Optional<T>, который явно указывает на возможность отсутствия значения. Аналогичные типы есть в C# (Nullable<T>), Swift (Optional), Kotlin и других языках. Использование Optional делает код более читаемым и снижает риск NullPointerException.

Аннотации и статический анализ

В языках со статической типизацией (Java, C#, Kotlin) используются аннотации (@Nullable, @NonNull) и инструменты статического анализа (например, IntelliJ IDEA, SpotBugs, Checker Framework), которые предупреждают о потенциальных null-ошибках на этапе компиляции.

Применение null в реальных проектах

Интересные факты

Критика

Концепция null подвергается критике по нескольким причинам:

Альтернативные подходы (опциональные типы, null-объекты, монады) считаются более безопасными и выразительными, хотя и требуют большего объёма кода в некоторых случаях.

Источники

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →