Что такое null java
Перейти к содержимому

Что такое null java

  • автор:

Разница между null и пустой строкой в Java: анализ сравнений

В Java строка со значением null ( String nullString = null; ) обозначает отсутствие ссылки на любой объект в памяти. Любые попытки вызвать методы у такой строки, например nullString.length() , приведут к выбрасыванию исключения NullPointerException . С другой стороны, пустая строка ( String emptyString = «»; ) является полноценным объектом, но его содержимое отсутствует, что позволяет без проблем вызывать методы, и emptyString.length() корректно вернёт 0. При прямом сравнении ( == ) null трактуется как отсутствие ссылки на объект, а пустая строка – как ссылка на объект без символов.

Скопировать код

String nullString = null; String emptyString = ""; // Проверка на null boolean isNull = (nullString == null); // true, объект отсутствует boolean isEmpty = (emptyString == null); // false, объект существует, но он пуст // Получение длины строки int emptyLength = emptyString.length(); // 0, строка пуста, но объект существует int nullLength = nullString.length(); // Вызовет NullPointerException, так как объект отсутствует

Основные различия

Прогараммируя на Java, необходимо помнить следующее о строках:

  • Ссылка null символизирует отсутствие любого объекта.
  • Пустая строка представляет собой объект, в котором нет символов ( length() == 0 ).
  • Символьные литералы, включая пустую строку, являются неизменяемыми в Java.
  • У null невозможно вызывать свойства или методы, поэтому попытка их вызова влечет за собой ошибку.
  • Сравнение null строки с пустой строкой при помощи == или equals() всегда возвращает false .

Сценарии использования

Изучение интернирования строк и равенства

Скопировать код

String s1 = ""; String s2 = ""; boolean literalEquality = (s1 == s2); // true, пустые строки сохраняются в пуле строк и имеют одинаковые ссылки

Анализ операций со строками

Скопировать код

String s = ""; // Эти операции допустимы для пустых строк char firstChar = s.charAt(0); // Вызовет StringIndexOutOfBoundsException, в пустой строке отсутствуют символы boolean isEmpty = s.isEmpty(); // true, строка не содержит символов String n = null; // Выполнение операций с null приведет к исключениям char firstChar = n.charAt(0); // Вызовет NullPointerException, ввиду отсутствия строки boolean isNull = n.isEmpty(); // Вызовет NullPointerException, у null невозможно вызывать методы

Изучение null-безопасных операций

Скопировать код

// Использование Apache Commons Lang boolean isBlank = StringUtils.isBlank(null); // true, null обозначает абсолютное отсутствие содержимого boolean isNotBlank = StringUtils.isNotBlank(""); // false, строка существует, однако пуста // Использование isBlank() из Java 11 boolean isBlankNative = "".isBlank(); // true, строка пуста и существует

Глубокое понимание разницы между null и пустой строкой

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

Проектирование с учетом null и пустых строк

Правильное разлиичение между null и пустой строкой может влиять на архитектурные решения. Если null может означать отсутствие данных, то использование пустой строки ( «» ) подразумевает, что значение было осознанно установлено как пустое.

Визуализация

Представьте театр, где вместа мест приходят в употребление значения переменных Java:

Статус места | Значение переменной | Пример в Java -------------- | ------------------- | ------------- �� (Пусто) | Место свободно, | String str = ""; | но не занято | �� (Null) | Место отсутствует, | String str = null; | места нет в наличии |

Иллюстрация Null и Пустой Строки:

  • «» (Пусто ��): В театре идёт спектакль, но никто не сидит на этом месте.
  • null (Нет места ��): Этого места просто нет, его нельзя предложить; оно не существует в принципе.

Усиление надежности вашего кода

Обработка null и пустых строк

  • Используйте условные проверки: Перед вызовом методов у строк всегда убеждайтесь в их не- null -состоянии, чтобы избежать NullPointerException .
  • Используйте Optional: С Java 8 доступно использование Optional для предотвращения появления нулевых ссылок.

Полезные материалы

  1. String (Java Platform SE 8) — Официальная документация на класс String Java SE 8.
  2. Check whether a String is not Null and not Empty – Trой дискуссии на Stack Overflow о проверках строк на null или пустоту.
  3. Difference Between null and an Empty String in Java — Статья на Baeldung, подробно описывающая различия между null и пустыми строками.
  4. Java67 — Сборник советов о наилучших способах проверки строк на пустоту или null в Java.
  5. Java String isEmpty() and isBlank() Methods — Учебное пособие от DigitalOcean, в котором объясняется использование и различия методов isEmpty() и isBlank().

Java: Значение null

Особняком в Java стоит значение null . В Java оно не является типом. Это просто конкретное значение со специальным смыслом и логикой работы. Начнем с примера:

// Определение переменной без инициализации значением // С var такое не сработает, так как невозможно вывести тип String a; 

Что находится внутри переменной a ? Если мы ее распечатаем, то увидим null . Значение null используется для ссылочных типов, когда значение не определено.

Как такое возможно? Представьте, что мы хотим извлечь из базы данных пользователя, а его там нет. Что вернет нам запрос в базу? Вот именно для таких ситуаций и нужен null .

Их гораздо больше, чем может показаться на первый взгляд. Чем дальше мы будем двигаться, тем чаще он начнет встречаться:

var user = // тут делаем запрос в базу // Если данных нет, то user станет null // Запись выше равносильна var user = null; 

Из вышесказанного следует важный вывод. Любой ссылочный тип данных может принимать значение null . То есть, null является значением любого ссылочного типа. А вот примитивные типы и null не совместимы. Примитивное значение всегда должно быть определено:

// Error: incompatible types: cannot be converted to int int x = null; 

Задание

Определите переменную с именем greeting , но не инициализируйте ее

Упражнение не проходит проверку — что делать? ��

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.

В моей среде код работает, а здесь нет ��

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя ��

Это нормально ��, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

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

Прочитал урок — ничего не понятно ��

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

Полезное

null — это экземпляр чего-то?

Нет такого типа, которому бы соответствовал instanceof от null .

RelationalExpression: RelationalExpression instanceof ReferenceType 

В рантайме результат оператора instanceof будет true , если значение RelationalExpression не null и ссылка может быть приведена к ReferenceType без получения исключения ClassCastException . Иначе результат будет false .

Это означает, что для любого типа E и R , для любого E o , где o == null , o instanceof R будет всегда false .

К какому типу принадлежит null ?

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

Что такое null ?

Как сказано в цитате из JLS выше, можно считать, что » null — это просто специальный литерал, который может быть любым ссылочным типом».

В Java null == null (что верно не для всех языков). Из описания java.lang.Object :

public boolean equals(Object obj)

Для любой не null переменной x , x.equals(null) должен возвращать false .

null также является значением по умолчанию для всех ссылочных типов.

  • Статические переменные класса, переменные экземпляра и массивы инициализируются значением по умолчанию при создании: * Для всех ссылочных типов (§4.3), дефолтное значение — null .

Вы можете использовать это свойства для отложенной инициализации, когда поле будет иметь начальное значение null до тех пор, пока оно фактически не будет использовано, где будет заменено «реальным» значением (вычисление которого может быть дорогостоящим).

Есть и другие применения. Если посмотреть на java.lang.System :

public static Console console()

Returns: The system console, if any, otherwise null.

Это очень распространённая практика: null используется для обозначения несуществующего объекта.

public String readLine() throws IOException

Returns: A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached.

readLine() будет возвращать instanceof String для каждой строки, пока не получит null , обозначающий конец. Это позволяет обрабатывать каждую строку следующим образом:

String line; while ((line = reader.readLine()) != null)

Примечание: пустая строка — не проблема, т.к. «» != null .

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

If this map permits null values, then a return value of null does not necessarily indicate that the map contains no mapping for the key; it’s also possible that the map explicitly maps the key to null . The containsKey operation may be used to distinguish these two cases.

Здесь мы видим, что использование null может усложнить дело. Тут говорится, что, если такого ключа нет, будет возвращён null . Второе утверждение гласит, что даже если элемент по такому ключу есть, всё равно может вернуться null .

К примеру, java.util.Hashtable делает вещи проще путём запрета null в ключах и значениях; так что, если V get(Object key) вернёт null это однозначно говорит о том, что под таким ключом ничего нет.

Операции автоматического анбоксинга на null выбросят java.lang.NullPointerException :

Integer i = null; // при анбоксинге null в integer будет выброшен NullPointerException int a = i; 

Если резюмировать, то null используется как специальное значение для обозначения:

  • Не инициализированного состояния.
  • Терминальное условие
  • Несуществующий объект.
  • Неизвестное значение.

Как null представлен в памяти?

The Java Virtual Machine specification does not mandate a concrete value encoding null .

Небольшое дополнение

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

Является ли null в Java объектом?

Java-университет

Является ли null объектом? Я могу совершенно точно сказать, что не является. В том смысле, что (null instanceof Object) выдаст значение false . Вот что ещё нужно знать о null:

Является ли null в Java объектом? - 1

  1. Вы не можете вызвать метод со значением null: x.m() выдаст ошибку, когда x является null, а m — нестатический метод. Кстати, если m — статический метод, товсё хорошо, поскольку важен только класс x , а значение игнорируется.
  2. Есть только один null на всех, а не отдельный для каждого класса. Таким образом, ((String) null == (Hashtable) null) , например.
  3. Вполне допустимо передавать null в качестве параметра методу, если метод это допускает (некоторые методы допускают null-параметр, другие — нет). Так, например, вы вполне можете написать System.out.println (null) , а вот butstring.compareTo (null) не получится. Так что всегда указывайте в javadoc-комментариях ваших методов, допустим ли null в качестве их параметров, если это не вполне очевидно.
  4. В JDK начиная с версии 1.1 и вплоть до 1.1.5 передача null в качестве литерального параметра(literal argument) конструктору анонимного внутреннего класса (например, new SomeClass(null) < . >вызывало ошибку компиллятора. Зато можно передать выражение со значением null, или передать принудительный null, в виде new SomeClass((String) null)
  5. Существует по меньшей мере три разных случая, которые обычно выражены с помощью null:
    • Uninitialized (отсутствие инициализации). Переменная или слот, которой ещё не присвоили никакго значения.
    • Non-existant/not applicable («не существует/не применимо»).Например, терминальные узлы бинарного дерева можно назвать обычными узлами с null-потомками.
    • Empty (пустота чего-либо). Например, вы можете использовать null чтобы представить пустое дерево. Обратите внимание, что это существенно отличается от предыдущего случая (на практике их часто путают). Разница заключается в том, является ли null приемлемым узлом дерева или null означает, что значение не нужно обрабатывать как узел дерева.

Сравните три реализации узлов бинарного дерева с методами последовательного вывода в консоль:

 // null означает «не применимо» // Здесь нет пустого дерева. class Node < Object data; Node left, right; void print() < if (left != null) left.print(); System.out.println(data); if (right != null) right.print(); >> 
 // null означает пустое дерево // обратите внимание на статические и нестатические методы class Node < Object data; Node left, right; void static print(Node node) < if (node != null) node.print(); >void print() < print(left); System.out.println(data); print(right); >> 
 // Отдельный класс для Empty // null не используется interface Node < void print(); >class DataNode implements Node < Object data; Node left, right; void print() < left.print(); System.out.println(data); right.print(); >> class EmptyNode implements Node < void print() < >> 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *