Null pointer exception in java что это
Перейти к содержимому

Null pointer exception in java что это

  • автор:

How to Handle Null Pointer Exception in Java

DJ

In Java, a special null value can be assigned to an object’s reference and denotes that the object is currently pointing to unknown piece of data. A NullPointerException is thrown when an application is trying to use or access an object whose reference equals to null . The following cases throw that exception:

  • Invoking a method from a null object.
  • Accessing or modifying a null object’s field.
  • Taking the length of null , as if it were an array.
  • Accessing or modifying the slots of null object, as if it were an array.
  • Throwing null , as if it were a Throwable value.
  • When you try to synchronize over a null object.

The NullPointerException is a RuntimeException and thus, the Javac compiler does not force you to use a try-catch block to handle it appropriately.

Why do we need the null value?

As already mentioned, null is a special value used in Java. It is extremely useful in coding some design patterns, such as Null Object pattern and Singleton pattern. The Null Object pattern provides an object as a surrogate for the lack of an object of a given type. The Singleton pattern ensures that only one instance of a class is created and also, aims for providing a global point of access to the object.

For example, a sample way to create at most one instance of a class is to declare all its constructors as private and then, create a public method that returns the unique instance of the class:

In this example, we declare a static instance of the Singleton class. That instance is initialized at most once inside the getInstance method. Notice the use of the null value that enables the unique instance creation.

How to avoid the NullPointerException

In order to avoid the NullPointerException , ensure that all your objects are initialized properly, before you use them. Notice that, when you declare a reference variable, you are really creating a pointer to an object. You must verify that the pointer is not null, before you request the method or a field from the object.

Also, if the exception is thrown, use the information residing in the exception’s stack trace. The execution’s stack trace is provided by the JVM, in order to enable the debugging of the application. Locate the method and the line where the exception was caught and then, figure out which reference equals to null in that specific line.

In the rest of this section, we will describe some techniques that deal with the aforementioned exception. However, they do not eliminate the problem and the programmer should always be careful while coding an application.

1. String comparison with literals

A very common case in an application’s execution code involves the comparison between a String variable and a literal. The literal may be a String or the element of an Enum. Instead of invoking the method from the null object, consider invoking it from the literal. For example, observe the following case:

The above code snippet will throw a NullPointerException . However, if we invoke the method from the literal, the execution flow continues normally:

2. Check the arguments of a method

Before executing the body of your own method, be sure to check its arguments for null values. Continue with the execution of the method, only when the arguments are properly checked. Otherwise, you can throw an IllegalArgumentException and notify the calling method that something is wrong with the passed arguments.

3. Prefer String.valueOf() method instead of toString()

When your application’s code requires the String representation of an object, avoid using the object’s toString method. If your object’s reference equals to null , a NullPointerException will be thrown.

Instead, consider using the static String.valueOf method, which does not throw any exceptions and prints "null" , in case the function’s argument equals to null .

4. Use the Ternary Operator

The ternary operator can be very useful and can help us avoid the NullPointerException . The operator has the form:

First, the boolean expression is evaluated. If the expression is true then, the value1 is returned, otherwise, the value2 is returned. We can use the ternary operator for handling null pointers as follows:

The message variable will be empty if str ’s reference is null. Otherwise, if str points to actual data, the message will retrieve the first 10 characters of it.

5. Create methods that return empty collections instead of null

A very good technique is to create methods that return an empty collection, instead of a null value. Your application’s code can iterate over the empty collection and use its methods and fields, without throwing a NullPointerException . For example:

6. Make use of Apache’s StringUtils class

Apache’s Commons Lang is a library that provides helper utilities for the java.lang API, such as String manipulation methods. A sample class that provides String manipulation is StringUtils.java , which handles null input Strings quietly.

You can make use of the StringUtils.isNotEmpty, StringUtils.IsEmpty and StringUtils.equals methods, in order to avoid the NullPointerException . For example:

7. Use the contains(), containsKey(), containsValue() methods

If your application code makes use of collections, such as Maps , consider using the contains, containsKey and containsValue methods. For example, retrieve the value of a specific key, after you have verified its existence in the map:

In the above snippet, we don’t check if the key actually exists inside the Map and thus, the returned value can be null . The safest way is the following:

8. Check the return value of external methods

It is very common in practice to make use of external libraries. These libraries contain methods that return a reference. Make sure that the returned reference is not null . Also, consider reading the Javadoc of the method, in order to better understand its functionality and its return values.

9. Use Assertions

Assertions are very useful while testing your code and can be used, in order to avoid executing code snippets that will throw a NullPointerException . Java Assertions are implemented with the assert keyword and throw an AssertionError .

Notice that you must explicitly enable the assertion flag of the JVM, by executing it with the –ea argument. Otherwise, the assertions will be completely ignored.

A sample example using Java assertions is the following:

If you execute the above code snippet and pass a null argument to getLength , the following error message will appear:

Exception in thread "main" java.lang.AssertionError

Finally, you can use the Assert class provided by the jUnit testing framework.

10. Unit Tests

Unit tests can be extremely useful while testing the functionality and correctness of your code. Devote some time to write a couple tests cases that verify that no NullPointerException is thrown, while your application’s code undergoes a specific execution flow.

Existing NullPointerException safe methods

1. Accessing static members or methods of a class

When your code attempts to access a static variable or method of a class, even if the object’s reference equals to null , the JVM does not throw a NullPointerException . This is due to the fact that the Java compiler stores the static methods and fields in a special place, during the compilation procedure. Thus, the static fields and methods are not associated with objects, rather with the name of the class.

For example, the following code does not throw a NullPointerException :

Notice, that despite the fact that the instance of the SampleClass equals to null , the method will be executed properly. However, when it comes to static methods or fields, it is better to access them in a static way, such as SampleClass.printMessage() .

2. The instanceof operator

The instanceof operator can be used, even if the object’s reference equals to null . The instanceof operator returns false when the reference equals to null and does not throw a NullPointerException . For example consider the following code snippet:

Как понять NullPointerException

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

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

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

Откуда-то был вызван метод 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 будет указывать на строку с вызовом.

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

Что такое Null Pointer Exception и как его исправить?

Что из себя представляет исключение Null Pointer Exception ( java.lang.NullPointerException ) и почему оно может происходить?

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

Anton Sorokin's user avatar

Nicolas Chabanovsky's user avatar

Когда вы объявляете переменную ссылочного типа, на самом деле вы создаете ссылку на объект данного типа. Рассмотрим следующий код для объявления переменной типа int:

В этом примере переменная x имеет тип int и Java инициализирует её как 0. Когда вы присвоите переменной значение 10 (вторая строка), это значение сохранится в ячейке памяти, на которую ссылается x .

Но когда вы объявляете ссылочный тип, процесс выглядит иначе. Посмотрим на следующий код:

В первой строке объявлена переменная num , ее тип не относится к встроенному, следовательно, значением является ссылка (тип этой переменной, Integer , является ссылочным типом). Поскольку вы еще не указали, на что собираетесь ссылаться, Java присвоит переменной значение Null , подразумевая «Я ни на что не ссылаюсь».

Во второй строке, ключевое слово new используется для создания объекта типа Integer . Этот объект имеет адрес в памяти, который присваивается переменной num . Теперь, с помощью переменной num вы можете обратиться к объекту используя оператора разыменования . .

Исключение, о котором вы говорите в вопросе, возникает, если вы объявили переменную, но не создали объект, то есть если вы попытаетесь разыменовать num до того, как создали объект, вы получите NullPointerException . В самом простом случае, компилятор обнаружит проблему и сообщит, что

num may not have been initialized

Что говорит: «возможно, переменная num не инициализирована».

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

В этом случае создание объекта (переменная num ) лежит на вызывающем коде, то есть вы предполагаете, что он был создан ранее – до вызова метода doSomething . К сожалению, следующий вызов метода вполне возможен:

В этом случае значение переменной num будет null . Лучшим способом избежать данного исключения будет проверка на равенство нулю. Как результат, функция doSomething должна быть переписана следующим образом:

Как альтернативный вариант предыдущему примеру вы можете сообщить вызывающему коду, что метод был вызван с неверными параметрами, например, с помощью IllegalArgumentException .

Java NullPointerException — Detect, Fix, and Best Practices

Java NullPointerException - Detect, Fix, and Best Practices

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

java.lang.NullPointerException is one of the most popular exceptions in java programming. Anybody working in java must have seen this popping out of nowhere in the java standalone program as well as the java web application.

java.lang.NullPointerException

java lang nullpointerexception hierarchy

NullPointerException is a runtime exception, so we don’t need to catch it in the program. NullPointerException is raised in an application when we are trying to do some operation on null where an object is required. Some of the common reasons for NullPointerException in java programs are:

  1. Invoking a method on an object instance but at runtime the object is null.
  2. Accessing variables of an object instance that is null at runtime.
  3. Throwing null in the program
  4. Accessing index or modifying value of an index of an array that is null
  5. Checking the length of an array that is null at runtime.

Java NullPointerException Examples

Let’s look at some examples of NullPointerException in java programs.

1. NullPointerException when calling an instance method

When we run the above program, it throws the following NullPointerException error message.

We are getting NullPointerException in the statement t.foo("Hi"); because “t” is null here.

2. Java NullPointerException while accessing/modifying field of a null object

The above program throws the following NullPointerException stack trace.

NullPointerException is being thrown in statement int i = t.x; because “t” is null here.

3. Java NullPointerException when null is passed in method argument

This is one of the most common occurrences of java.lang.NullPointerException because it’s the caller who is passing the null argument.

The below image shows the null pointer exception when the above program is executed in Eclipse IDE.

Exception in thread main java.lang.NullPointerException

4. java.lang.NullPointerException when null is thrown

Below is the exception stack trace of the above program, showing NullPointerException because of throw null; statement.

5. NullPointerException when getting the length of null array

6. NullPointerException when accessing index value of null array

7. NullPointerException when synchronized on a null object

The synchronized(mutex) will throw NullPointerException because the “mutex” object is null.

8. HTTP Status 500 java.lang.NullPointerException

Sometimes we get an error page response from a java web application with an error message as “HTTP Status 500 – Internal Server Error” and root cause as java.lang.NullPointerException .

For this, I edited the Spring MVC Example project and changed the HomeController method as below.

The below image shows the error message thrown by the web application response.

http error 500 java lang nullpointerexception

Here is the exception stack trace:

The root cause is NullPointerException in the statement user.getUserId().toLowerCase() because user.getUserId() is returning null.

How to detect java.lang.NullPointerException

Detecting NullPointerException is very easy, just look at the exception trace and it will show you the class name and line number of the exception. Then look at the code and see what could be null causing the NullPointerException. Just look at all the above examples, it’s very clear from stack trace what is causing null pointer exception.

How to fix NullPointerException

java.lang.NullPointerException is an unchecked exception, so we don’t have to catch it. The null pointer exceptions can be prevented using null checks and preventive coding techniques. Look at below code examples showing how to avoid java.lang.NullPointerException .

Coding Best Practices to avoid NullPointerException

1. Let’s consider the below function and look out for scenario causing null pointer exception.

The NullPointerException can occur if the argument is being passed as null. The same method can be written as below to avoid NullPointerException.

2. We can also add null check for argument and throw IllegalArgumentException if required.

3. We can use ternary operator as shown in the below example code.

4. Use String.valueOf() rather than toString() method. For example check PrintStream println() method code is defined as below.

The below code snippet shows the example where the valueOf() method is used instead of toString().

5. Write methods returning empty objects rather than null wherever possible, for example, empty list, empty string, etc.

6. There are some methods defined in collection classes to avoid NullPointerException, you should use them. For example contains(), containsKey(), and containsValue().

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

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

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