internal exception java lang nullpointerexception как исправить
Ошибка java.lang.nullpointerexception, как исправить?
Ряд пользователей (да и разработчиков) программных продуктов на языке Java могут столкнуться с ошибкой java.lang.nullpointerexception (сокращённо NPE), при возникновении которой запущенная программа прекращает свою работу. Обычно это связано с некорректно написанным телом какой-либо программы на Java, требуя от разработчиков соответствующих действий для исправления проблемы. В этом материале я расскажу, что это за ошибка, какова её специфика, а также поясню, как исправить ошибку java.lang.nullpointerexception.
Что это за ошибка java.lang.nullpointerexception
Появление данной ошибки знаменует собой ситуацию, при которой разработчик программы пытается вызвать метод по нулевой ссылке на объект. В тексте сообщения об ошибке система обычно указывает stack trace и номер строки, в которой возникла ошибка, по которым проблему будет легко отследить.
Что в отношении обычных пользователей, то появление ошибки java.lang.nullpointerexception у вас на ПК сигнализирует, что у вас что-то не так с функционалом пакетом Java на вашем компьютере, или что программа (или онлайн-приложение), работающие на Java, функционируют не совсем корректно. Если у вас возникает проблема, при которой Java апплет не загружен, рекомендую изучить материал по ссылке.
Как исправить ошибку java.lang.nullpointerexception
Как избавиться от ошибки java.lang.nullpointerexception? Способы борьбы с проблемой можно разделить на две основные группы – для пользователей и для разработчиков.
Для пользователей
Если вы встретились с данной ошибкой во время запуска (или работы) какой-либо программы (особенно это касается minecraft), то рекомендую выполнить следующее:
Для разработчиков
Разработчикам стоит обратить внимание на следующее:
Что такое исключение NullPointerException и как его исправить?
Что такое исключения Null Pointer ( java.lang.NullPointerException ) и что их вызывает?
Какие методы / инструменты можно использовать для определения причины, чтобы исключить исключение из-за преждевременного прекращения работы программы?
Когда вы объявляете ссылочную переменную (то есть объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int :
В этом примере переменная x является int и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но, когда вы пытаетесь объявить ссылочный тип, происходит что-то другое. Возьмите следующий код:
Например, у вас может быть следующий метод:
В этом случае obj равно null. Если метод предназначен для того, чтобы что-то сделать с переданным объектом, целесообразно бросить NullPointerException потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
В качестве альтернативы могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным объектом, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:
Наконец, как определить местоположение исключения и вызвать использование Stack Trace
В первой строке внутри main я явно устанавливаю ссылку Object obj равной нулю. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обрабатывать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
Что такое исключение NullPointerException?
Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
Приложения должны бросать экземпляры этого класса, чтобы указать на другое незаконное использование нулевого объекта.
Как это исправить?
Определите нулевые значения
Трассировка, в которой эти значения исходят из
Трассировка, где эти значения должны быть установлены
Другие исправления
Переменная может иметь значение по умолчанию (и setName может помешать ей установить значение null):
Или вы можете создать класс так, чтобы name всегда имело ненулевое значение :
Смотрите также:
Я все еще не могу найти проблему
Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).
NullPointerException во время выполнения, когда ваша программа пытается использовать null как если бы она была реальной ссылкой. Например, если вы пишете это:
Вопрос: Как мне узнать стек NPE?
Предположим, что я компилирую и запускаю программу выше:
Поэтому давайте посмотрим, что говорит:
Первая строка трассировки стека сообщает вам несколько вещей:
Вторая строка является наиболее важной при диагностике NPE.
Это говорит нам о нескольких вещах:
И если вы подсчитаете строки в файле выше, строка 4 – это та, которую я обозначил комментарием «ЗДЕСЬ».
Короче говоря, stacktrace скажет нам однозначно, какой из программ программы бросил NPE.
1 – Не совсем верно. Есть вещи, называемые вложенными исключениями …
Вопрос: Как определить причину исключения NPE в моем коде?
Это трудная часть. Короткий ответ заключается в применении логического вывода к доказательствам, предоставленным трассировкой стека, исходным кодом и соответствующей документацией API.
Давайте сначала проиллюстрируем простым примером (см. Выше). Мы начинаем с рассмотрения строки, о которой нам рассказали stacktrace, где происходит NPE:
Как это может вызвать NPE?
Итак, откуда это произошло? В этом случае это очевидно, и очевидно, что нам нужно сделать, чтобы исправить это. (Назначьте ненулевое значение для foo )
Итак, теперь у нас есть 2 строки «на линии». Первая – для этой строки:
А вторая – для этой строки:
Итак, глядя на первую строчку, как это может вызвать NPE? Фактически, есть два способа:
Поэтому нам нужно выяснить, какой из этих сценариев объясняет, что происходит на самом деле. Давайте начнем с изучения первого:
В самом деле! И в этом проблема. Когда мы инициализируем так:
Исключение нулевого указателя бросается, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
Приложения должны бросать экземпляры этого класса, чтобы указать на другое незаконное использование null объекта.
В общем, это потому, что что-то не было правильно инициализировано.
См. Также: Хороший список лучших практик
Я бы добавил, очень важно, использовать final модификатор.
Использование «окончательного» модификатора, когда это применимо в java
Резюме:
В Java все вещи находятся в форме класса.
Если вы хотите использовать любой объект, то у вас есть две фазы
То же самое для концепции Array
Исключение с нулевым указателем – это индикатор того, что вы используете Object без его инициализации.
Например, ниже – класс студентов, который будет использоваться в нашем коде.
Ниже код дает вам исключение нулевого указателя.
Поскольку вы используете Obj_Student но вы забыли его инициализировать, как показано на рисунке ниже.
В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не сами объекты.
Когда вы пытаетесь выполнить один метод объекта, ссылка запрашивает у живого объекта выполнение этого метода. Но если ссылка ссылается на NULL (ничего, ноль, void, nada), то нет способа, которым метод будет выполнен. Затем среда выполнения сообщит вам об этом, выбросив исключение NullPointerException.
Объект живет в пространстве памяти VM, и единственный доступ к нему – this использование this ссылок. Возьмем следующий пример:
Это важно знать – когда больше нет ссылок на объект (в приведенном выше примере, когда ссылка «reference» и «otherReference» указывает на null), объект «недоступен». Мы не можем работать с ним, поэтому этот объект помечен для сбора мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.
Другое появление NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разглядеть элементы внутри него.
Вы должны инициализировать элементы в массиве перед тем, как получить доступ к ним или разблокировать их.
Что такое исключение NullPointerException и как его исправить?
Что такое исключения Null Pointer ( java.lang.NullPointerException ) и что их вызывает?
Какие методы/инструменты могут быть использованы для определения причины, чтобы исключить исключение из-за преждевременного завершения программы?
ОТВЕТЫ
Ответ 1
Когда вы объявляете ссылочную переменную (т.е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int :
Но когда вы пытаетесь объявить ссылочный тип, происходит что-то другое. Возьмите следующий код:
NullPointerException возникает, когда вы объявляете переменную, но не создаете объект. Таким образом, вы указываете на то, чего на самом деле не существует.
Например, у вас может быть следующий метод:
Альтернативно, могут быть случаи, когда целью метода является не только работа с переданным объектом, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething() можно записать так:
Ответ 2
(Это техничность, но я думаю, что она упоминает: ссылка, указывающая на нуль, не совпадает с указателем на C, указывающим на недопустимую ячейку памяти. Нулевой указатель буквально не указывает нигде, что тонко отличается от указания на местоположение, которое оказалось недействительным.)
Ответ 3
Что такое исключение NullPointerException?
Хорошим местом для начала является JavaDocs. Они охватывают:
Брошено, когда приложение пытается использовать null в случае, когда объект требуется. К ним относятся:
Приложения должны бросать экземпляры этого класса, чтобы указать другие незаконное использование нулевого объекта.
Как это исправить?
Определите нулевые значения
Здесь мы видим, что исключение выбрано в строке 13 (в методе printString ). Посмотрите на строку и проверьте, какие значения равны нулю добавление операторов регистрации или использование отладчика. Мы обнаруживаем, что s имеет значение null, и вызов метода length на нем вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.
Трассировка, где эти значения взяты из
Трассировка, где эти значения должны быть установлены
Другие исправления
У переменной может быть значение по умолчанию (и setName может помешать ему установить значение null):
Любой метод print или printString может проверять значение null, например:
Или вы можете создать класс так, чтобы name всегда имел ненулевое значение:
См. также:
Я все еще не могу найти проблему
Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включает stacktrace в вопросе, а отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE).
Ответ 4
Вопрос: Что вызывает NullPointerException (NPE)?
Вопрос: Как я прочитал стек стека NPE?
Предположим, что я компилирую и запускаю программу выше:
Первое наблюдение: компиляция завершается успешно! Проблема в программе НЕ является ошибкой компиляции. Это ошибка времени выполнения. (Некоторые IDE могут предупредить, что ваша программа всегда будет генерировать исключение. но стандартный javac компилятор не делает.)
Второе наблюдение: при запуске программы он выводит две строки «gobbledy-gook». НЕПРАВИЛЬНО!!. Это не ласково. Это stacktrace. и он предоставляет важную информацию, которая поможет вам отследить ошибку в вашем коде, если вы потратите время, чтобы внимательно прочитать ее.
Итак, давайте посмотрим, что он говорит:
Первая строка трассировки стека сообщает вам несколько вещей:
Вторая строка является наиболее важной при диагностике NPE.
Это говорит нам о многом:
Короче говоря, трассировка стека однозначно скажет нам, какая инструкция программы выбрала NPE.
Вопрос: Как определить причину исключения NPE в моем коде?
Это трудная часть. Короткий ответ заключается в применении логического вывода к доказательствам, предоставленным трассировкой стека, исходным кодом и соответствующей документацией API.
Сначала проиллюстрируем простой пример (см. выше). Мы начнем с просмотра строки, о которой рассказывал нам стек, где находится NPE:
Как это может вызвать NPE?
Хорошо, давайте попробуем немного более хитрый пример. Для этого потребуется некоторый логический вывод.
Глядя на первую строчку, как это может вызвать NPE? Существует два способа:
Затем нам нужно выяснить, какой из этих сценариев объясняет, что на самом деле происходит. Мы начнем с изучения первого:
В самом деле, это так! И в этом проблема. Когда мы инициализируем так:
Ответ 5
В это время вы только что объявили этот объект, но не инициализировали или не инстанцировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException что имеет смысл.
См. Также пример ниже:
Ответ 6
Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
Ответ 7
В общем, потому что что-то не было правильно инициализировано.
Ответ 8
Краткое описание:
Ответ 9
Например, ниже приведен класс ученика, который будет использовать его в нашем коде.
Код ниже дает исключение нулевого указателя.
Ответ 10
В Java все (кроме примитивных типов) имеет форму класса.
Если вы хотите использовать какой-либо объект, то у вас есть две фазы:
То же самое для концепции массива:
Ответ 11
В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не сами объекты.
Когда вы пытаетесь выполнить один метод объекта, ссылка запрашивает у живого объекта выполнение этого метода. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Затем среда выполнения сообщит вам об этом, выбросив исключение NullPointerException.
Ваша ссылка «указывает» на нуль, таким образом «Null → Pointer».
И на другом месте в вашем коде:
Ответ 12
Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разглядеть элементы внутри него.
Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.
Как исправить ошибку java.lang.nullpointerexception?
В этом посте я покажу наглядный пример того, как исправить ошибку исключения Null Pointer (java.lang.nullpointerexception). В Java особое значение null может быть назначено для ссылки на объект и означает, что объект в данный момент указывает неизвестную область данных.
NullPointerException появляется, если программа обращается или получает доступ к объекту, а ссылка на него равна нулю (null).
Это исключение возникает следующих случаях:
NullPointerException является RuntimeException, и, таким образом, компилятор Javac не заставляет вас использовать блок try-catch для соответствующей обработки.
Зачем нам нужно значение null?
Как уже упоминалось, null — это специальное значение, используемое в Java. Это чрезвычайно полезно при кодировании некоторых шаблонов проектирования, таких как Null Object pattern и шаблон Singleton pattern.
Шаблон Singleton обеспечивает создание только одного экземпляра класса, а также направлен на предоставление глобального доступа к объекту.
Например, простой способ создания не более одного экземпляра класса — объявить все его конструкторы как частные, а затем создать открытый метод, который возвращает уникальный экземпляр класса:
В этом примере мы объявляем статический экземпляр класса Singleton. Этот экземпляр инициализируется не более одного раза внутри метода getInstance.
Обратите внимание на использование нулевого значения, которое разрешает создание уникального экземпляра.
Как избежать исключения Null Pointer
Чтобы решить и избежать исключения NullPointerException, убедитесь, что все ваши объекты инициализированы должным образом, прежде чем использовать их.
Когда вы объявляете ссылочную переменную, вы должны создать указатель на объект и убедиться, что указатель не является нулевым, прежде чем запрашивать метод или поле у объекта.
Кроме того, если выдается исключение, используйте информацию, находящуюся в трассировке стека исключения. Трассировка стека выполнения обеспечивается JVM, чтобы включить отладку. Найдите метод и строку, в которой было обнаружено исключение, а затем выясните, какая ссылка равна нулю в этой конкретной строке.
Опишем некоторые методы, которые имеют дело с вышеупомянутым исключением. Однако они не устраняют проблему, и программист всегда должен быть осторожен.
Очень распространенный случай, выполнения программы включает сравнение между строковой переменной и литералом. Литерал может быть строкой или элементом Enum.
Вместо того, чтобы вызывать метод из нулевого объекта, рассмотрите возможность вызова его из литерала. Например:
Приведенный выше фрагмент кода вызовет исключение NullPointerException. Однако, если мы вызываем метод из литерала, поток выполнения продолжается нормально:
Перед выполнением вашего собственного метода обязательно проверьте его аргументы на наличие нулевых значений.
В противном случае вы можете вызвать исключение IllegalArgumentException.
Когда код вашей программы требует строковое представление объекта, избегайте использования метода toString объекта. Если ссылка вашего объекта равна нулю, генерируется исключение NullPointerException.
Вместо этого рассмотрите возможность использования статического метода String.valueOf, который не выдает никаких исключений и «ноль», если аргумент функции равен нулю.
Ternary Operator — может быть очень полезным. Оператор имеет вид:
Сначала вычисляется логическое выражение. Если выражение true, то возвращается значение1, в противном случае возвращается значение2. Мы можем использовать Ternary Operator для обработки нулевых указателей следующим образом:
Переменная message будет пустой, если ссылка str равна нулю. В противном случае, если str указывает на фактические данные, в сообщении будут первые 10 символов.
Очень хорошая техника — создавать методы, которые возвращают пустую коллекцию вместо нулевого значения. Код вашего приложения может перебирать пустую коллекцию и использовать ее методы и поля. Например:
Apache’s Commons Lang – это библиотека, которая предоставляет вспомогательные утилиты для API java.lang, такие как методы манипулирования строками.
Примером класса, который обеспечивает манипулирование String, является StringUtils.java, который спокойно обрабатывает входные строки с нулевым значением.
Вы можете воспользоваться методами: StringUtils.isNotEmpty, StringUtils.IsEmpty и StringUtils.equals, чтобы избежать NullPointerException. Например:
Если в коде вашего приложения используется Maps, рассмотрите возможность использования методов contains, containsKey и containsValue. Например, получить значение определенного ключа после того, как вы проверили его существование на карте:
System.out.println(value.toString()); // В приведенном выше фрагменте мы не проверяем, существует ли на самом деле ключ внутри карты, и поэтому возвращаемое значение может быть нулевым. Самый безопасный способ следующий:
На практике очень часто используются внешние библиотеки. Эти библиотеки содержат методы, которые возвращают ссылку. Убедитесь, что возвращаемая ссылка не пуста.
Утверждения очень полезны при тестировании вашего кода и могут использоваться, чтобы избежать выполнения фрагментов кода. Утверждения Java реализуются с помощью ключевого слова assert и выдают AssertionError.
Примером использования утверждений Java является такая версия кода:
Если вы выполните приведенный выше фрагмент кода и передадите пустой аргумент getLength, появится следующее сообщение об ошибке:
Exception in thread «main» java.lang.AssertionError
Также вы можете использовать класс Assert предоставленный средой тестирования jUnit.
Модульные тесты могут быть чрезвычайно полезны при тестировании функциональности и правильности вашего кода. Уделите некоторое время написанию пары тестовых примеров, которые подтверждают, что исключение NullPointerException не возникает.
Существующие безопасные методы NullPointerException
Доступ к статическим членам или методам класса
Когда ваш вы пытаетесь получить доступ к статической переменной или методу класса, даже если ссылка на объект равна нулю, JVM не выдает исключение.
Это связано с тем, что компилятор Java хранит статические методы и поля в специальном месте во время процедуры компиляции. Статические поля и методы связаны не с объектами, а с именем класса.
Несмотря на тот факт, что экземпляр SampleClass равен нулю, метод будет выполнен правильно. Однако, когда речь идет о статических методах или полях, лучше обращаться к ним статическим способом, например, SampleClass.printMessage ().
Оператор instanceof
Оператор instanceof может использоваться, даже если ссылка на объект равна нулю.
Оператор instanceof возвращает false, когда ссылка равна нулю.
В результате, как и ожидалось:
Not an instance of the String class!
Смотрите видео, чтобы стало понятнее.
Средняя оценка / 5. Количество голосов:
Или поделись статьей
Видим, что вы не нашли ответ на свой вопрос.
Как понять NullPointerException
Эта простая статья скорее для начинающих разработчиков Java, хотя я нередко вижу и опытных коллег, которые беспомощно глядят на stack trace, сообщающий о NullPointerException (сокращённо NPE), и не могут сделать никаких выводов без отладчика. Разумеется, до NPE своё приложение лучше не доводить: вам помогут null-аннотации, валидация входных параметров и другие способы. Но когда пациент уже болен, надо его лечить, а не капать на мозги, что он ходил зимой без шапки.
Рассмотрим такой код:
Откуда-то был вызван метод 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):
Вызываем метод 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 будет указывать на строку с вызовом.
В заключение хочется пожелать пореже запускать отладчик: после некоторой тренировки анализ кода в голове нередко выполняется быстрее, чем воспроизведение трудноуловимой ситуации.