Java string null error

Как понять NullPointerException

Эта простая статья скорее для начинающих разработчиков Java, хотя я нередко вижу и опытных коллег, которые беспомощно глядят на stack trace, сообщающий о NullPointerException (сокращённо NPE), и не могут сделать никаких выводов без отладчика. Разумеется, до NPE своё приложение лучше не доводить: вам помогут null-аннотации, валидация входных параметров и другие способы. Но когда пациент уже болен, надо его лечить, а не капать на мозги, что он ходил зимой без шапки.

Итак, вы узнали, что ваше приложение упало с NPE, и у вас есть только stack trace. Возможно, вам прислал его клиент, или вы сами увидели его в логах. Давайте посмотрим, какие выводы из него можно сделать.

NPE может произойти в трёх случаях:

  1. Его кинули с помощью throw
  2. Кто-то кинул null с помощью throw
  3. Кто-то пытается обратиться по null-ссылке

Во втором и третьем случае message в объекте исключения всегда null, в первом может быть произвольным. К примеру, java.lang.System.setProperty кидает NPE с сообщением «key can’t be null», если вы передали в качестве key null. Если вы каждый входной параметр своих методов проверяете таким же образом и кидаете исключение с понятным сообщением, то вам остаток этой статьи не потребуется.

Обращение по null-ссылке может произойти в следующих случаях:

  1. Вызов нестатического метода класса
  2. Обращение (чтение или запись) к нестатическому полю
  3. Обращение (чтение или запись) к элементу массива
  4. Чтение length у массива
  5. Неявный вызов метода valueOf при анбоксинге (unboxing)

Важно понимать, что эти случаи должны произойти именно в той строчке, на которой заканчивается stack trace, а не где-либо ещё.

Рассмотрим такой код:

Откуда-то был вызван метод handle с какими-то параметрами, и вы получили:

В чём причина исключения — в f, d или d.val? Нетрудно заметить, что f в этой строке вообще не читается, так как метод format статический. Конечно, обращаться к статическому методу через экземпляр класса плохо, но такой код встречается (мог, например, появиться после рефакторинга). Так или иначе значение f не может быть причиной исключения. Если бы d был не null, а d.val — null, тогда бы исключение возникло уже внутри метода format (в девятой строчке). Аналогично проблема не могла быть внутри метода getValue, даже если бы он был сложнее. Раз исключение в пятнадцатой строчке, остаётся одна возможная причина: null в параметре d.

Вот другой пример:

Снова вызываем метод handle и получаем

Теперь метод format нестатический, и f вполне может быть источником ошибки. Зато s не может быть ни под каким соусом: в девятой строке уже было обращение к s. Если бы s было null, исключение бы случилось в девятой строке. Просмотр логики кода перед исключением довольно часто помогает отбросить некоторые варианты.

С логикой, конечно, надо быть внимательным. Предположим, условие в девятой строчке было бы написано так:

Теперь в самой строчке обращения к полям и методам s нету, а метод equals корректно обрабатывает null, возвращая false, поэтому в таком случае ошибку в двенадцатой строке мог вызвать как f, так и s. Анализируя вышестоящий код, уточняйте в документации или исходниках, как используемые методы и конструкции реагируют на null. Оператор конкатенации строк +, к примеру, никогда не вызывает NPE.

Вот такой код (здесь может играть роль версия Java, я использую Oracle JDK 1.7.0.45):

READ  Installation has failed there was an error while installing the application discord

Вызываем метод dump, получаем такое исключение:

В параметре pw не может быть null, иначе нам не удалось бы войти в метод print. Возможно, null в obj? Легко проверить, что pw.print(null) выводит строку «null» без всяких исключений. Пойдём с конца. Исключение случилось здесь:

В строке 473 возможна только одна причина NPE: обращение к методу length строки s. Значит, s содержит null. Как так могло получиться? Поднимемся по стеку выше:

В метод write передаётся результат вызова метода String.valueOf. В каком случае он может вернуть null?

Единственный возможный вариант — obj не null, но obj.toString() вернул null. Значит, ошибку надо искать в переопределённом методе toString() нашего объекта MyObject. Заметьте, в stack trace MyObject вообще не фигурировал, но проблема именно там. Такой несложный анализ может сэкономить кучу времени на попытки воспроизвести ситуацию в отладчике.

Не стоит забывать и про коварный автобоксинг. Пусть у нас такой код:

И такое исключение:

На первый взгляд единственный вариант — это null в параметре obj. Но следует взглянуть на класс MyContainer:

Мы видим, что getCount() возвращает Integer, который автоматически превращается в int именно в третьей строке TestNPE.java, а значит, если getCount() вернул null, произойдёт именно такое исключение, которое мы видим. Обнаружив класс, подобный классу MyContainer, посмотрите в истории системы контроля версий, кто его автор, и насыпьте ему крошек под одеяло.

Помните, что если метод принимает параметр int, а вы передаёте Integer null, то анбоксинг случится до вызова метода, поэтому NPE будет указывать на строку с вызовом.

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

Источник

Как исправить ошибку java.lang.nullpointerexception?

В этом посте я покажу наглядный пример того, как исправить ошибку исключения Null Pointer (java.lang.nullpointerexception). В Java особое значение null может быть назначено для ссылки на объект и означает, что объект в данный момент указывает неизвестную область данных.

NullPointerException появляется, если программа обращается или получает доступ к объекту, а ссылка на него равна нулю (null).

Это исключение возникает следующих случаях:

  • Вызов метода из объекта значения null.
  • Доступ или изменение объекта поля null.
  • Принимает длину null(если бы это был массив Java).
  • Доступ или изменение ячеек объекта null.
  • Показывает «0», значение Throwable.
  • При попытке синхронизации по нулевому объекту.

NullPointerException является RuntimeException, и, таким образом, компилятор Javac не заставляет вас использовать блок try-catch для соответствующей обработки.

Зачем нам нужно значение null?

Как уже упоминалось, null – это специальное значение, используемое в Java. Это чрезвычайно полезно при кодировании некоторых шаблонов проектирования, таких как Null Object pattern и шаблон Singleton pattern.

Шаблон Singleton обеспечивает создание только одного экземпляра класса, а также направлен на предоставление глобального доступа к объекту.

Например, простой способ создания не более одного экземпляра класса – объявить все его конструкторы как частные, а затем создать открытый метод, который возвращает уникальный экземпляр класса:

В этом примере мы объявляем статический экземпляр класса Singleton. Этот экземпляр инициализируется не более одного раза внутри метода getInstance.

Обратите внимание на использование нулевого значения, которое разрешает создание уникального экземпляра.

Как избежать исключения Null Pointer

Чтобы решить и избежать исключения NullPointerException, убедитесь, что все ваши объекты инициализированы должным образом, прежде чем использовать их.

Когда вы объявляете ссылочную переменную, вы должны создать указатель на объект и убедиться, что указатель не является нулевым, прежде чем запрашивать метод или поле у ​​объекта.

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

READ  Lenovo vibe one прошивка

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

  1. Сравнение строк с литералами

Очень распространенный случай, выполнения программы включает сравнение между строковой переменной и литералом. Литерал может быть строкой или элементом Enum.

Вместо того, чтобы вызывать метод из нулевого объекта, рассмотрите возможность вызова его из литерала. Например:

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

  1. Проверка аргументов метода

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

В противном случае вы можете вызвать исключение IllegalArgumentException.

  1. Предпочтение метода String.valueOf() вместо of toString()

Когда код вашей программы требует строковое представление объекта, избегайте использования метода toString объекта. Если ссылка вашего объекта равна нулю, генерируется исключение NullPointerException.

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

  1. Используйте Ternary Operator

Ternary Operator – может быть очень полезным. Оператор имеет вид:

boolean expression ? value1 : value2;

Сначала вычисляется логическое выражение. Если выражение true, то возвращается значение1, в противном случае возвращается значение2. Мы можем использовать Ternary Operator для обработки нулевых указателей следующим образом:

String message = (str == null) ? «» : str.substring(0, 10);

Переменная message будет пустой, если ссылка str равна нулю. В противном случае, если str указывает на фактические данные, в сообщении будут первые 10 символов.

  1. создайте методы, которые возвращают пустые коллекции вместо нуля.

Очень хорошая техника – создавать методы, которые возвращают пустую коллекцию вместо нулевого значения. Код вашего приложения может перебирать пустую коллекцию и использовать ее методы и поля. Например:

  1. Воспользуйтесь классом Apache’s StringUtils.

Apache’s Commons Lang – это библиотека, которая предоставляет вспомогательные утилиты для API java.lang, такие как методы манипулирования строками.

Примером класса, который обеспечивает манипулирование String, является StringUtils.java, который спокойно обрабатывает входные строки с нулевым значением.

Вы можете воспользоваться методами: StringUtils.isNotEmpty, StringUtils.IsEmpty и StringUtils.equals, чтобы избежать NullPointerException. Например:

  1. Используйте методы: contains(), containsKey(), containsValue()

Если в коде вашего приложения используется Maps, рассмотрите возможность использования методов contains, containsKey и containsValue. Например, получить значение определенного ключа после того, как вы проверили его существование на карте:

System.out.println(value.toString()); // В приведенном выше фрагменте мы не проверяем, существует ли на самом деле ключ внутри карты, и поэтому возвращаемое значение может быть нулевым. Самый безопасный способ следующий:

  1. Проверьте возвращаемое значение внешних методов

На практике очень часто используются внешние библиотеки. Эти библиотеки содержат методы, которые возвращают ссылку. Убедитесь, что возвращаемая ссылка не пуста.

Утверждения очень полезны при тестировании вашего кода и могут использоваться, чтобы избежать выполнения фрагментов кода. Утверждения Java реализуются с помощью ключевого слова assert и выдают AssertionError.

Обратите внимание, что вы должны включить флажок подтверждения JVM, выполнив его с аргументом -ea. В противном случае утверждения будут полностью проигнорированы.

Примером использования утверждений Java является такая версия кода:

Если вы выполните приведенный выше фрагмент кода и передадите пустой аргумент getLength, появится следующее сообщение об ошибке:
Exception in thread «main» java.lang.AssertionError
Также вы можете использовать класс Assert предоставленный средой тестирования jUnit.

Модульные тесты могут быть чрезвычайно полезны при тестировании функциональности и правильности вашего кода. Уделите некоторое время написанию пары тестовых примеров, которые подтверждают, что исключение NullPointerException не возникает.

Существующие безопасные методы NullPointerException

Доступ к статическим членам или методам класса

Когда ваш вы пытаетесь получить доступ к статической переменной или методу класса, даже если ссылка на объект равна нулю, JVM не выдает исключение.

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

Несмотря на тот факт, что экземпляр SampleClass равен нулю, метод будет выполнен правильно. Однако, когда речь идет о статических методах или полях, лучше обращаться к ним статическим способом, например, SampleClass.printMessage ().

Оператор instanceof

Оператор instanceof может использоваться, даже если ссылка на объект равна нулю.

READ  The computer restarted unexpectedly or encountered an unexpected error на ноутбуке

Оператор instanceof возвращает false, когда ссылка равна нулю.

В результате, как и ожидалось:

Not an instance of the String class!

Смотрите видео, чтобы стало понятнее.

Средняя оценка 4 / 5. Количество голосов: 9

Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.

Или поделись статьей

Видим, что вы не нашли ответ на свой вопрос.

Помогите улучшить статью.

Напишите комментарий, что можно добавить к статье, какой информации не хватает.

Источник

How to Fix and Avoid NullPointerException in Java

Table of Contents

The java.lang.NullPointerException is a runtime exception in Java that occurs when a variable is accessed which is not pointing to any object and refers to nothing or null.

Since the NullPointerException is a runtime exception, it doesn’t need to be caught and handled explicitly in application code.

Why NullPointerException Occurs in Java

The NullPointerException occurs due to a situation in application code where an uninitialized object is attempted to be accessed or modified. Essentially, this means the object reference does not point anywhere and has a null value.

Some of the most common scenarios for a NullPointerException are:

  • Calling methods on a null object
  • Accessing a null object’s properties
  • Accessing an index element (like in an array) of a null object
  • Passing null parameters to a method
  • Incorrect configuration for dependency injection frameworks like Spring
  • Using synchronized on a null object
  • Throwing null from a method that throws an exception

NullPointerException Example

Here is an example of a NullPointerException thrown when the length() method of a null String object is called:

In this example, the printLength() method calls the length() method of a String without performing a null check prior to calling the method. Since the value of the string passed from the main() method is null, running the above code causes a NullPointerException :

How to Fix NullPointerException

To fix the NullPointerException in the above example, the string should be checked for null or empty values before it is used any further:

The code is updated with a check in the printLength() method that makes sure the string is not empty using the apache commons StringUtils.isNotEmpty() method. Only if the string is not empty the length() method of the string is called, else it prints the message Empty string to console.

How to Avoid NullPointerException

The NullPointerException can be avoided using checks and preventive techniques like the following:

  1. Making sure an object is initialized properly by adding a null check before referencing its methods or properties.
  2. Using Apache Commons StringUtils for String operations e.g. using StringUtils.isNotEmpty() for verifying if a string is empty before using it further.
  3. Using primitives rather than objects where possible, since they cannot have null references e.g. using int instead of Integer and boolean instead of Boolean .

Track, Analyze and Manage Java Errors With Rollbar

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates Java error monitoring and triaging, making fixing errors easier than ever. Try it today!

Источник

Smartadm.ru