avatarUğur Taş

Summary

The article discusses methods to handle and avoid NullPointerExceptions in Java method chains to ensure code reliability and quality.

Abstract

The article "Eliminating NullPointerExceptions in Method Chains" addresses the common issue of NullPointerExceptions (NPEs) in Java, particularly in nested method calls. It emphasizes the importance of a reliable code base by handling NPEs effectively. The author presents four strategies to avoid NPEs in chained get calls: explicit null checks for each object, using try-catch blocks to handle exceptions, wrapping objects with Optional for safe navigation, and employing a generic method to centralize exception handling. The author advocates for the generic method approach as the most efficient, as it minimizes code verbosity and provides a centralized mechanism for handling NPEs, thus enhancing application stability and code predictability.

Opinions

  • The author believes that explicit null checks lead to verbose and hard-to-read code, which can decrease code reliability.
  • Using try-catch blocks is seen as a viable method to handle NPEs but may not be the most elegant solution.
  • The use of Optional is recognized as a way to prevent NPEs by checking for the presence of values at each step, though it can result in verbose code blocks.
  • The author's preferred method is a generic method using Supplier and Optional to handle NPEs, considering it the best practice for preventing application crashes due to null values in method chains.
  • The article suggests that preventing or gracefully handling NPEs is crucial for creating stable applications and more predictable code bases.
  • The author values reader feedback and encourages sharing and discussion of the content to foster a community of learning and improvement.

Eliminating NullPointerExceptions in Method Chains

How to avoid NullPointerException in chained get calls? If you are looking for an answer to this question, you are in the right place.

If you want to have a reliable code base, the first thing you need to do is try to avoid NullPointerException and handle possible NullPointerExceptions gracefully. Sometimes this is difficult to do because avoiding NullPointerException can make your code base ugly, decrease the reliability of the code, etc.

In this article, I will mention the ways to avoid and handle possible NullPointerExceptions in chained method calls. I hope this article helps you to increase the code quality of your project.

Let's first identify the issue. When we have lots of nested objects and want to reach a specific value, we need to make many get calls to retrieve the value. Consider below example,

user.getUserDetails().getContactDetails().getPhoneNumbers().get(0);

When you have a similar nested structure like the above example, you need to chain many get calls to get the phone number of the user. But the problem is this code is vulnerable and can break the application because of NullPointerException. In this example, user , userDetails , contactDetails , and phoneNumbers can be null and cause a NullPointerException. You can use four different methods to avoid application crash that occurs because of NPE.

1. Make a Null Check for Every Object

Here two example way of doing it.

if(user != null && 
   user.getUserDetails() != null && 
   user.getUserDetails().getContactDetails() != null && 
   user.getUserDetails().getContactDetails().getPhoneNumbers() != null && 
   user.getUserDetails().getContactDetails().getPhoneNumbers().get(0) != null) {
    user.getUserDetails().getContactDetails().getPhoneNumbers().get(0);
    // use the phone number 
}
if(user != null) {
   var userDetails = user.getUserDetails();
   if(userDetails != null) {
     var contactDetails = user.getUserDetails().getContactDetails();
     if(contactDetails != null) {
       var phoneNumbers = user.getUserDetails().getContactDetails().getPhoneNumbers();
       if(phoneNumbers != null) {
         var phoneNumber = user.getUserDetails().getContactDetails().getPhoneNumbers().get(0);
         if(phoneNumber != null) {
          // use the phone number 
         }
       }
     }
   }
}

Both of the above strategies are verbose and ugly code. It is hard to read also.

2. Wrap with Try-Catch Block and Catch the NPE

The second way of solving this issue is wrapping the statement with try-catch block and handling the NullPointerException.

try {
  var phoneNumber = user.getUserDetails().getContactDetails().getPhoneNumbers().get(0);
  // use the phone number
} catch (NullPointerException exp) {
  // handle possible exception case
}

3. Wrap with Optional

You can wrap the main object with Optional and map the all values step by step to get the phoneNumber object.

Optional.ofNullable(user)
        .map(user -> user.getUserDetails())
        .map(userDetails -> userDetails.getContactDetails())
        .map(contactDetails -> contactDetails.getPhoneNumbers())
        .map(phoneNumbers -> phoneNumbers.get(0))
        .orElse("Default Number");

Optional mapping prevents the NPE by checking the existence of the value at every step. But it again requires many lines of code and verbose code blocks.

4. Use Generic Method to Get the Value

This is the best way to minimize the required lines of code and centralize the NullPointerException handling. We can get the whole statement as a parameter of the method and process this statement in the generic method.

public static <T> Optional<T> optional(Supplier<T> statement) {
    try {
        T value = statement.get();
        return Optional.of(value);
    } catch (NullPointerException exp) {
        LOG.warn("Generic method caught a statement : {} with NPE : ", statement, exp);
        return Optional.empty();
    }
}

With the Supplier parameter, we are able to retrieve the value from the statement. In case a null value exists in the chained calls, we can catch the exception and handle it properly. Sample usage of this generic method is like this.

optional(
  () -> user.getUserDetails().getContactDetails().getPhoneNumbers().get(0)
).ifPresent(// do something with phone number)

There is a difference between this generic method and Optional.ofNullable(). If chained method calls have a null value, then Optional.ofNullable does not prevent throwing the exception. But this method provides an option to handle it. That’s why, I consider this generic method as the best way to prevent crashes that occur because of the NullPointerException.

Preventing NullPointerExceptions or handling them gracefully helps you to have stable applications and more predictable code bases. So it is important to consider possible cases that can cause an NPE and either avoid them or handle them before it crashes your application.

👏 Thank You for Reading!

👨‍💼 I appreciate your time and hope you found this story insightful. If you enjoyed it, don’t forget to show your appreciation by clapping 👏 for the hard work and subscribe

📰 Keep the Knowledge Flowing by Sharing the Article!

✍ Feel free to share your feedback or opinions about the story. Your input helps me improve and create more valuable content for you.

✌ Stay Connected! 🚀 For more engaging articles, make sure to follow me on social media:

🔍 Explore More! 📖 Dive into a treasure trove of knowledge at Codimis. There’s always more to learn, and we’re here to help you on your journey of discovery.

Java
Method Chaining
Null Safety
Nullpointerexception
Recommended from ReadMedium