Class name is null android

Как понять 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):

Вызываем метод 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, как исправить?

Ряд пользователей (да и разработчиков) программных продуктов на языке 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), то рекомендую выполнить следующее:

  1. Переустановите пакет Java на своём компьютере. Скачать пакет можно, к примеру, вот отсюда;
  2. Переустановите саму проблемную программу (или удалите проблемное обновление, если ошибка начала появляться после такового);
  3. Напишите письмо в техническую поддержку программы (или ресурса) с подробным описанием проблемы и ждите ответа, возможно, разработчики скоро пофиксят баг.
  4. Также, в случае проблем в работе игры Майнкрафт, некоторым пользователям помогло создание новой учётной записи с административными правами, и запуск игры от её имени.

Для разработчиков

Разработчикам стоит обратить внимание на следующее:

Источник

Учимся избегать null-значений в современном Java. Часть 2

Oct 13, 2020 · 8 min read

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

Возвращайте Optional вместо null

Хоть в предыдущей статье я и убеждал вас в уместности null для некоторых сценариев, в этой я буду напротив говорить, что по возможности его все же лучше избегать. При каждом добавлении в базу кода нового метода, способного вернуть пустое значение, вам следует стараться использовать вместо null тип Optional. Этот тип был введен, чтобы разработчики могли указывать на возможность возвращения методом пустого значения, что ранее было недоступно (либо требовало аннотаций, о которых я расскажу ниже). Существует два вида объектов Optional : содержащие значение и без него. Первые изначально создаются со значением, вторые же просто являются статическими одиночками. Структурно типичный случай их использования выглядит так:

Чтобы увидеть, почему сигнатура с Optional предпочтительней, представьте следующий метод:

Из этой сигнатуры понятно лишь, что она возвращает объект типа Admission . При этом, как уже говорилось, null соответствует любому типу. У нас нет иной возможности узнать, возвращает ли данный метод null , кроме как проанализировать его реализацию. В противоположность приведенному примеру, метод, возвращающий Optional , будет выглядеть так:

Поскольку смысл использовать Optional есть только в случае возможного возврата пустого значения, значит метод такое значение вернуть может. Поэтому при каждом возвращении Optional методом вы знаете, что есть вероятность получения пустого значения и его нужно должным образом обработать.

Читайте также:  Sms bomber antichrist андроид

Возвращаемое значение Optional обрабатывается аналогично null : вы проверяете, передано ли значение, и, если да — выполняете с ним определенные действия. Вызов метода, возвращающего null , как правило, выглядит так:

Со значением Optional соответствующий код будет выглядеть так:

В то время как можно легко забыть выполнить проверку на null в первом примере, тип Optional безопаснее и делает очевидным возможное отсутствие возвращаемого значения. Если вы вызовите get() для пустого значения Optional , то получите исключение, как и в случае вызова любого метода для значения null . В самых простых случаях перед вызовом get() всегда нужно вызывать isPresent() , однако API предлагает и другие альтернативы, где при отсутствии значения может возвращаться его предустановленный вариант.

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

Однако если бы вместо этого у нас был метод, возвращающий активную госпитализацию, то предпочтительнее было бы использовать Optional :

Можно ли использовать Optional для параметров?

SonarLint отвечает “Нет”, поскольку лучше предоставить действительное значение, чем Optional , которое может его иметь или нет. Ведь иначе нам придется проверять в методе оба случая, а также убеждаться, что никто не передал вместо него null. Смешивать же null и Optional вообще не стоит, иначе смысл в использовании последнего полностью исчезнет.

Никогда не делайте следующее, равно как не предоставляйте null в качестве аргумента параметра с Optional значением:

Если вы сделаете нечто подобное, то также получите NPE (исключение нулевого указателя).

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

Содействуйте IDE с помощью аннотаций Nullable/Nonnull

Для большинства баз кода полное отсутствие null в передаче данных является утопией. Еще одним способом прояснить ваши намерения и одновременно помочь системе типов помочь вам — это использовать для параметров и возвращаемых значений аннотации, которые указывают, где стоит ожидать null , а где нет, а также где его использование предполагается. Такую возможность предлагают рзаные фреймворки, но основная идея одна: параметр можно снабдить либо тегом Nonnull , сообщая, что значение null для него ожидать не нужно, либо Nullable , указывая обратное. Добавление тегов допустимо также для полей и возвращаемых значений.

Вот один из примеров подобной сигнатуры метода:

Сейчас эта сигнатура показывает, что метод не предполагает вызов с параметром Patient , содержащим null , и если такой вызов произойдет, IDE выдаст предупреждение. При этом мы также проинформированы, что данный метод может вернуть null , и вы аналогичным образом получите предупреждение при использовании этого возвращаемого значения метода.

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

Используйте Objects.requireNonNull()

Аннотации имеют значение только во время компиляции и не влияют на поведение программы при выполнении. Если вам нужно, чтобы при выполнении метод не вызывался с null -аргументом, то следует использовать метод Objects.requireNonNull (T obj, строка сообщения). Объекты — это статический служебный класс для выполнения основных операций вроде equals , hashCode и toString , защищенным от null способом.

Чтобы оградить метод от нулевых аргументов, передайте в метод requireNonNull() соответствующие параметры вместе с описательным текстом ошибки. Если параметр окажется null , это вызовет NPE с указанным вами сообщением об ошибке. В противном случае данный метод просто вернет параметр. Обычно его используют в конструкторах, как показано ниже:

Здесь у вас может возникнуть вопрос, заключается ли причина избегания нулевого параметра в том, что он может ненамеренно привести к NPE. Не будет ли лучше выбросить NPE намеренно до того, как это произойдет?

Читайте также:  Файлы для андроид архивом

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

Предположим, вы получаете NPE в следующей строке кода:

Какая из переменных была null ? И bar , и baz , и qux могли оказаться нулевыми. Если qux не была null , то объект, который она возвращает, мог. Потребуется потратить какое-то время на выяснение, какой из этих сценариев оказался виновником.

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

Работа со строками

Я часто вижу баги там, где логике при генерации строк не удается учесть нулевые значения, в результате чего среди строк пользовательского интерфейса появляется null . Причина такого коварного поведения в том, что в Java при конкатенации строк неожиданное нулевое значение не ведет к NPE до тех пор, пока для него явно не вызываются методы. Если мы заглянем внутрь JRE, то выясним, что null-значения часто явно обрабатываются и преобразуются в null — значения. Каждый раз, когда мы используем сокращение “ + ”, генерируется StringBuilder и используется для создания объединенного значения. Это означает, что правосторонние значения присваиваний s3 и s4 по факту эквивалентны:

В обоих случаях получится строка hello null . Конкатенацию также можно выполнить при помощи s1.concat(s2) , и это, что интересно, будет вызывать NPE всякий раз, когда s2 будет null . Тем не менее метод concat не является предпочтительным несмотря на то, что справляется лучше StringBuilder при конкатенации всего нескольких строк. В связи с этим мы, как правило, будем обнаруживать null -строки лишь в UI.

Используйте класс Objects и библиотеку StringUtils

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

Тернарный оператор часто используется для возвращения предустановленного значения, когда переменная содержит null . Ниже приведен пример этого, взятый прямо из нашей базы кода Columna:

Примечательно, что это не самый сложный для анализа код, но я думаю, что его можно написать гораздо лучше. В C# существует так называемый оператор объединения с неопределенным значением, относящийся к тернарному оператору, явно проверяющему значение на null . Вот пример:

Здесь левое значение оператора присваивается, если оно не null , в противном случае используется правая сторона. Несмотря на то, что в Java недостает подобного оператора, с той же целью можно использовать встроенный класс Objects , описанный выше. Метод toString(Object o, String s) класса Objects возвращает значение toString() первого объекта, если этот объект не null , в противном случае он возвращает указанное строковое значение.

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

Используйте StringUtils для защиты String-методов от null

Библиотека StringUtils упрощает обработку null и пустых строк. В API это описывается как: “Защищенные от null операции со String.” Эта библиотека содержит много стандартных строковых операций со встроенными проверками на null . При ее использовании база кода станет менее громоздкой, так как вам не потребуется реализовывать весь рутинный код проверок на null , и читать условные выражения станет легче. При этом база кода также станет более единообразной, и что более важно, код станет безопаснее, так как вы уже ненароком не забудете реализовать проверки нулевых значений. В частности, такая агрессивная защита выражений конкатенации с условными инструкциями на основе метода isBlank(s) гарантирует, что в строки уже не проскользнут нежелательные “null”-значения.

Заключение

Вкратце содержание рассмотренной серии статей можно выразить так:

Источник

Оцените статью