Goran Martinic
Goran Martinic

Reputation: 3827

How do I avoid checking for nulls in Java?

I use x != null to avoid NullPointerException. Is there an alternative?

if (x != null) {
    // ...
}

Upvotes: 4428

Views: 1448093

Answers (30)

lalithBR
lalithBR

Reputation: 11

Handling null before processing is common approach. However if you can guarantee that incoming data is not null you can proceed without null checking(very risky).

Upvotes: 0

Premakumar Tatireddy
Premakumar Tatireddy

Reputation: 85

Objects.isNull(null) If you are using Java8 then you can try this code.

String value = null;
    
    if (Objects.isNull(value)) {
        System.out.println("The value is null.");
    } else {
        System.out.println("The value is not null.");
    }

Try using the below code if you are not using Java8

Object ob=null;
if(ob==null){
    //do something
}

Upvotes: 1

CodeForFood
CodeForFood

Reputation: 117

  • For Java 8, you can use the Optional class. Optional provides lots of methods like ifPresent(), isPresent(), orElse(), ofNullable(), orElseThrow(), etc.

    String value = "Mr. Bean";
    
    Optional<String> optionalValue = Optional.ofNullable(value);
    optionalValue.ifPresent(value -> System.out.println(value));
    
    Optional<String> optionalValue = Optional.ofNullable(value);
    String result = optionalValue.orElse("Not Found"); // returns "Not Found" if value is null
    
  • For Java 7 and later, you use Objects Utility Class

    String result = Objects.requireNonNull(value, "Value can't be null");
    

It throws a NullPointerException with a custom message.

  • Also, you can use Objects.nonNull

    if (Objects.nonNull(value)) {
       // logic
    }
    

Upvotes: 0

Larry Cable
Larry Cable

Reputation: 116

use the new pattern matching syntax of 'instanceof' ... since instanceof tests for null...

if (obj instanceof SomeType st) { }

although this is only really useful with a narrowing type cast...

Upvotes: 0

Paul Tofunmi
Paul Tofunmi

Reputation: 530

I would recommend immutable objects. This practice is recommend in many coding practices and useful as industries such as financial services.

With immutability, Immutable objects cannot be changed after creation. This means fields are set at construction and never modified. This naturally eliminates nulls for those fields.

public final class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
}

Benefits:

  • Predictability: Once created, you're guaranteed the object's state won't change unexpectedly.
  • Thread safety: Immutable objects are inherently thread-safe.
  • Reduced Null Checks: No need to check if fields may have been changed to null.

You can achieve the above solution using code generators like Lombok also.

Upvotes: 1

Oleg
Oleg

Reputation: 443

Common "problem" in Java indeed.

First, my thoughts on this:

I consider that it is bad to "eat" something when NULL was passed where NULL isn't a valid value. If you're not exiting the method with some sort of error then it means nothing went wrong in your method which is not true. Then you probably return null in this case, and in the receiving method you again check for null, and it never ends, and you end up with "if != null", etc..

So, IMHO, null must be a critical error that prevents further execution (that is, where null is not a valid value).

The way I solve this problem is this:

First, I follow this convention:

  1. All public methods / API always check their arguments for null
  2. All private methods do not check for null since they are controlled methods (just let die with nullpointer exception in case it wasn't handled above)
  3. The only other methods which do not check for null are utility methods. They are public, but if you call them for some reason, you know what parameters you pass. This is like trying to boil water in the kettle without providing water...

And finally, in the code, the first line of the public method goes like this:

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

Note that addParam() returns self, so that you can add more parameters to check.

Method validate() will throw checked ValidationException if any of the parameters is null (checked or unchecked is more a design/taste issue, but my ValidationException is checked).

void validate() throws ValidationException;

The message will contain the following text if, for example, "plans" is null:

"Illegal argument value null is encountered for parameter [plans]"

As you can see, the second value in the addParam() method (string) is needed for the user message, because you cannot easily detect passed-in variable name, even with reflection (not the subject of this post anyway...).

And yes, we know that beyond this line we will no longer encounter a null value so we just safely invoke methods on those objects.

This way, the code is clean, easily maintainable, and readable.

Upvotes: 40

Pierre Henry
Pierre Henry

Reputation: 17497

Java 8 introduced the java.util.Optional class that addresses some of the problem. One can at least say that it improves the readability of the code, and in the case of public APIs make the contract clearer to the client developer.

They work as follows:

An optional object for a given type (Fruit) is created as the return type of a method. It can be empty or contain a Fruit object:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

Now look at this code where we search a list of Fruit (fruits) for a given Fruit instance:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get(); // Prefer found.orElseThrow() in Java 9+
   String name = fruit.getName();
}

You can use the map method to perform a computation on — or extract a value from — an optional object. The orElse method lets you provide a fallback for missing values, converting an Optional to a non-nullable value.

String nameOrFallback = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

Of course, handling the null/empty value is still necessary, but at least the developer is conscious that the value might be empty and the risk of forgetting to check is limited.

In an API built from scratch using Optional whenever a return value might be empty, and returning a plain object only when it cannot be null (convention), the client code might abandon null checks on simple object return values.

Of course Optional could also be used as a method argument, perhaps a better way to indicate optional arguments than 5 or 10 overloading methods in some cases. Be aware that using it in this manner is recommended against by Java Language Architect Brian Goetz: "You should almost never use Optional as […] a method parameter."

Optional offers other convenient methods, such as orElseGet that calculates a default value only if the Optional is empty, and ifPresent that peforms an operation only if the Optional is non-empty, both of which work with lambda expressions.

I invite you to read this article (the main source for writing this answer) in which the problematic behavior of NullPointerException (and in general null pointer) and the (partial) solution brought by Optional are well explained: Java Optional Objects.

Upvotes: 192

Prabhat Kumar
Prabhat Kumar

Reputation: 17

We can use 'Objects.requireNonNull' to avoid explicit null checks.

For Ex.

public class Main {

    private String myString;

    public Main(String myString) {
        this.myString = Objects.requireNonNull(myString, "myString must not be null");


    }
}

Upvotes: -1

Sahi Repswal
Sahi Repswal

Reputation: 340

It can be handled by this:

import org.apache.commons.lang.ObjectUtils;
if(!ObjectUtils.equals(x, null)){

}

Upvotes: 0

Geoffrey
Geoffrey

Reputation: 494

This is a big question ans the only valid answer is: You cannot avoid to check for null in java.

The issue comes from the language syntax itself, an object can always be both typed or null. Even an Optional object can be null.

All of the other proposals (annotations, optional ...) add just more boilerplate code around the issue but never really solve it. And even worse will add more and more complexity and corner cases to handle manually.

The only viable solution is to not write the boilerplate yourself and let another tool do it for you. That is when you use Kotlin. null safety was a major concern when they designed the language.

Also the java syntax will never change so deeply because it will imply some major breaking changes, creating a new language in fact (what kotlin already did at the end).

That is the major reason why so many companies moved to kotlin recently. Check some articles about Facebook, Google android ...

And one of the major issue in the java world is that many people learned java so long ago that they are emotionally attached to it and don't want to change their habit. So they try to justify their weird and obsolete pattern instead of just using a meta language, like TypeScript for JavaScript in the frontend world.

Upvotes: 0

Greg7000
Greg7000

Reputation: 425

Personally, I would either go with jim-nelson's answer or if I do find a null check is convenient for a specific context I would incorporate lombok into my project and use the @NonNull annotation.

Example:

import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;
  
  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}

Even the @NonNull preface mention:

  • or: How I learned to stop worrying and love the NullPointerException.

Upvotes: 2

J-J
J-J

Reputation: 5871

If you are using java8 or later go for the isNull(yourObject) from java.util.Objects.

Example:-

String myObject = null;

Objects.isNull(myObject); //will return true

Usage: The below code returns a non null value (if the name is not null then that value will be returned else the default value will be returned).

final String name = "Jobin";
String nonNullValue = Optional.ofNullable(name).orElse("DefaultName");

Upvotes: 5

cletus
cletus

Reputation: 625307

This to me sounds like a reasonably common problem that junior to intermediate developers tend to face at some point: they either don't know or don't trust the contracts they are participating in and defensively overcheck for nulls. Additionally, when writing their own code, they tend to rely on returning nulls to indicate something thus requiring the caller to check for nulls.

To put this another way, there are two instances where null checking comes up:

  1. Where null is a valid response in terms of the contract; and

  2. Where it isn't a valid response.

(2) is easy. As of Java 1.7 you can use Objects.requireNonNull(foo). (If you are stuck with a previous version then assertions may be a good alternative.)

"Proper" usage of this method would be like below. The method returns the object passed into it and throws a NullPointerException if the object is null. This means that the returned value is always non-null. The method is primarily intended for validating parameters.

public Foo(Bar bar) {
    this.bar = Objects.requireNonNull(bar);
}

It can also be used like an assertion though since it throws an exception if the object is null. In both uses, a message can be added which will be shown in the exception. Below is using it like an assertion and providing a message.

Objects.requireNonNull(someobject, "if someobject is null then something is wrong");
someobject.doCalc();

Generally throwing a specific exception like NullPointerException when a value is null but shouldn't be is favorable to throwing a more general exception like AssertionError. This is the approach the Java library takes; favoring NullPointerException over IllegalArgumentException when an argument is not allowed to be null.

(1) is a little harder. If you have no control over the code you're calling then you're stuck. If null is a valid response, you have to check for it.

If it's code that you do control, however (and this is often the case), then it's a different story. Avoid using nulls as a response. With methods that return collections, it's easy: return empty collections (or arrays) instead of nulls pretty much all the time.

With non-collections it might be harder. Consider this as an example: if you have these interfaces:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

where Parser takes raw user input and finds something to do, perhaps if you're implementing a command line interface for something. Now you might make the contract that it returns null if there's no appropriate action. That leads the null checking you're talking about.

An alternative solution is to never return null and instead use the Null Object pattern:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Compare:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

to

ParserFactory.getParser().findAction(someInput).doSomething();

which is a much better design because it leads to more concise code.

That said, perhaps it is entirely appropriate for the findAction() method to throw an Exception with a meaningful error message -- especially in this case where you are relying on user input. It would be much better for the findAction method to throw an Exception than for the calling method to blow up with a simple NullPointerException with no explanation.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

Or if you think the try/catch mechanism is too ugly, rather than Do Nothing your default action should provide feedback to the user.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

Upvotes: 2872

Alex Worden
Alex Worden

Reputation: 3415

I'm a fan of "fail fast" code. Ask yourself - are you doing something useful in the case where the parameter is null? If you don't have a clear answer for what your code should do in that case... i.e. - it should never be null in the first place, then ignore it and allow a NullPointerException to be thrown. The calling code will make just as much sense of an NPE as it would an IllegalArgumentException, but it'll be easier for the developer to debug and understand what went wrong if an NPE is thrown rather than your code attempting to execute some other unexpected contingency logic - which ultimately results in the application failing anyway.

Upvotes: 98

Dan Chase
Dan Chase

Reputation: 1042

The best way to avoid Null Checks in Java, is to properly handle and use exceptions. Null Checks in my experience have become more common and required as you move closer to the front-end, because it's closer to the user who may supply invalid information through the UI (such as, no value, being submitted for a field).

One may argue that you should be able to control what the UI is doing, lest you forget most UI is done through a third party library of some kind, which for example, may return either NULL or an Empty String for a blank text box, depending on the situation or the library.

You can combine the two like this:

try
{
  myvar = get_user_supplied_value(); 
  if (myvar == null || myvar.length() == 0) { alert_the_user_somehow(); return; };

  process_user_input(myvar);
} catch (Exception ex) {
  handle_exception(ex);
}

Another approach people take is to say:

if (myvar && myvar.length() > 0)  { };

You could also throw an exception (which is what I prefer)

if (myvar == null || myvar.length() == 0) {
 throw new Exception("You must supply a name!");
};

But that's up to you.

Upvotes: 0

Allen
Allen

Reputation: 88

There has a good way to check the null value from JDK. It is Optional.java that has a sea of methods to resolve these problems. Such as follow:

    /**
     * Returns an {@code Optional} describing the specified value, if non-null,
     * otherwise returns an empty {@code Optional}.
     *
     * @param <T> the class of the value
     * @param value the possibly-null value to describe
     * @return an {@code Optional} with a present value if the specified value
     * is non-null, otherwise an empty {@code Optional}
     */
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
    /**
     * Return {@code true} if there is a value present, otherwise {@code false}.
     *
     * @return {@code true} if there is a value present, otherwise {@code false}
     */
    public boolean isPresent() {
        return value != null;
    }
    /**
     * If a value is present, invoke the specified consumer with the value,
     * otherwise do nothing.
     *
     * @param consumer block to be executed if a value is present
     * @throws NullPointerException if value is present and {@code consumer} is
     * null
     */
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

It is really, really useful to help javer.

Upvotes: 3

rohit prakash
rohit prakash

Reputation: 575

Java 8 has introduced a new class Optional in java.util package. It is used to represent a value is present or absent. The main advantage of this new construct is that No more too many null checks and NullPointerException. It avoids any runtime NullPointerExceptions and supports us in developing clean and neat Java APIs or Applications. Like Collections and arrays, it is also a Container to hold at most one value.

Below are some useful link you can follow

https://www.mkyong.com/java8/java-8-optional-in-depth/

https://dzone.com/articles/java-8-optional-avoid-null-and

Upvotes: 8

vidy
vidy

Reputation: 1640

public class Null {

public static void main(String[] args) {
    String str1 = null;
    String str2 = "";

    if(isNullOrEmpty(str1))
        System.out.println("First string is null or empty.");
    else
        System.out.println("First string is not null or empty.");

    if(isNullOrEmpty(str2))
        System.out.println("Second string is null or empty.");
    else
        System.out.println("Second string is not null or empty.");
}

public static boolean isNullOrEmpty(String str) {
    if(str != null && !str.isEmpty())
        return false;
    return true;
}
}

Output

str1 is null or empty.
str2 is null or empty.

In the above program, we've two strings str1 and str2. str1 contains null value and str2 is an empty string.

We've also created a function isNullOrEmpty() which checks, as the name suggests, whether the string is null or empty. It checks it using a null check using != null and isEmpty() method of string.

In plain terms, if a string isn't a null and isEmpty() returns false, it's not either null or empty. Else, it is.

However, the above program doesn't return empty if a string contains only whitespace characters (spaces). Technically, isEmpty() sees it contains spaces and returns false. For string with spaces, we use the string method trim() to trim out all the leading and trailing whitespace characters.

Upvotes: 3

Satish Hawalppagol
Satish Hawalppagol

Reputation: 184

You can make one generic Method for object and string so that you can use it through out in your application- This could help you and your colleagues : Create a class eg. StringUtilities and add the method eg. getNullString

public static String getNullString(Object someobject)
{
   if(null==someobject )
        return null;

   else if(someobject.getClass().isInstance("") && 
          (((String)someobject).trim().equalsIgnoreCase("null")|| 
          ((String)someobject).trim().equalsIgnoreCase("")))
        return null;

   else if(someobject.getClass().isInstance(""))
        return (String)someobject;

   else
        return someobject.toString().trim();
}

And simply call this method as,

if (StringUtilities.getNullString(someobject) != null)
{ 
  //Do something
}

Upvotes: 0

xtofl
xtofl

Reputation: 41519

Asking that question points out that you may be interested in error handling strategies. How and where to handle errors is a pervasive architectural question. There are several ways to do this.

My favorite: allow the Exceptions to ripple through - catch them at the 'main loop' or in some other function with the appropriate responsibilities. Checking for error conditions and handling them appropriately can be seen as a specialized responsibility.

Sure do have a look at Aspect Oriented Programming, too - they have neat ways to insert if( o == null ) handleNull() into your bytecode.

Upvotes: 39

SebastianBrandt
SebastianBrandt

Reputation: 459

Another alternative to the != null check is (if you can't get rid of it design-wise):

Optional.ofNullable(someobject).ifPresent(someobject -> someobject.doCalc());

or

Optional.ofNullable(someobject).ifPresent(SomeClass::doCalc);

With SomeClass being someobject's type.

You can't get a return value back from doCalc() though, so only useful for void methods.

Upvotes: 4

Luca Molteni
Luca Molteni

Reputation: 5370

If you use (or planning to use) a Java IDE like JetBrains IntelliJ IDEA, Eclipse or Netbeans or a tool like findbugs then you can use annotations to solve this problem.

Basically, you've got @Nullable and @NotNull.

You can use in method and parameters, like this:

@NotNull public static String helloWorld() {
    return "Hello World";
}

or

@Nullable public static String helloWorld() {
    return "Hello World";
}

The second example won't compile (in IntelliJ IDEA).

When you use the first helloWorld() function in another piece of code:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

Now the IntelliJ IDEA compiler will tell you that the check is useless, since the helloWorld() function won't return null, ever.

Using parameter

void someMethod(@NotNull someParameter) { }

if you write something like:

someMethod(null);

This won't compile.

Last example using @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Doing this

iWantToDestroyEverything().something();

And you can be sure that this won't happen. :)

It's a nice way to let the compiler check something more than it usually does and to enforce your contracts to be stronger. Unfortunately, it's not supported by all the compilers.

In IntelliJ IDEA 10.5 and on, they added support for any other @Nullable @NotNull implementations.

See blog post More flexible and configurable @Nullable/@NotNull annotations.

Upvotes: 719

Ramprabhu
Ramprabhu

Reputation: 195

Functional approach may help to wrap the repetitive null checks and execute anonymous code like the below sample.

    BiConsumer<Object, Consumer<Object>> consumeIfPresent  = (s,f) ->{
        if(s!=null) {
            f.accept(s);
        }
    };

    consumeIfPresent.accept(null, (s)-> System.out.println(s) );
    consumeIfPresent.accept("test", (s)-> System.out.println(s));

    BiFunction<Object, Function<Object,Object>,Object> executeIfPresent  = (a,b) ->{
        if(a!=null) {
            return b.apply(a);
        }
        return null;
    };
    executeIfPresent.apply(null, (s)-> {System.out.println(s);return s;} );
    executeIfPresent.apply("test", (s)-> {System.out.println(s);return s;} );

Upvotes: 0

Francis
Francis

Reputation: 7114

Kotlin with null safety is elegant alternative, but it means a larger change.

Upvotes: 1

Mukesh A
Mukesh A

Reputation: 323

You can avoid most a lot to avoid NullPointerException by just following most of the others answers to the Question, I just want to add few more ways which have been introduced in Java 9 to handle this scenario gracefully and also showcase a few of the older ones can also be used and thus reducing your efforts.

  1. public static boolean isNull(Object obj)

    Returns true if the provided reference is null otherwise returns false.

    Since Java 1.8

  2. public static boolean nonNull(Object obj)

    Returns true if the provided reference is non-null otherwise returns false.

    Since Java 1.8

  3. public static <T> T requireNonNullElse​(T obj, T defaultObj)

    Returns the first argument if it is non-null and otherwise returns the non-null second argument.

    Since Java 9

  4. public static <T> T requireNonNullElseGet​(T obj, Supplier<? extends T> supplier)

    Returns the first argument if it is non-null and otherwise returns the non-null value of supplier.get().

    Since Java 9

  5. public static <T> T requireNonNull​(T obj, Supplier<String> messageSupplier)

    Checks that the specified object reference is not null and throws a customized NullPointerException otherwise.

    Since Java 1.8

Further details about the above functions can be found here.

Upvotes: 8

echox
echox

Reputation: 9850

Only for this situation -

Not checking if a variable is null before invoking an equals method (a string compare example below):

if ( foo.equals("bar") ) {
 // ...
}

will result in a NullPointerException if foo doesn't exist.

You can avoid that if you compare your Strings like this:

if ( "bar".equals(foo) ) {
 // ...
}

Upvotes: 216

Mykhaylo Adamovych
Mykhaylo Adamovych

Reputation: 20976

Null is not a 'problem'. It is an integral part of a complete modeling tool set. Software aims to model the complexity of the world and null bears its burden. Null indicates 'No data' or 'Unknown' in Java and the like. So it is appropriate to use nulls for these purposes. I don't prefer the 'Null object' pattern; I think it rise the 'who will guard the guardians' problem.
If you ask me what is the name of my girlfriend I'll tell you that I have no girlfriend. In the Java language I'll return null. An alternative would be to throw meaningful exception to indicate some problem that can't be (or don't want to be) solved right there and delegate it somewhere higher in the stack to retry or report data access error to the user.

  1. For an 'unknown question' give 'unknown answer'. (Be null-safe where this is correct from business point of view) Checking arguments for null once inside a method before usage relieves multiple callers from checking them before a call.

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }
    

    Previous leads to normal logic flow to get no photo of a non-existent girlfriend from my photo library.

    getPhotoOfThePerson(me.getGirlfriend())
    

    And it fits with new coming Java API (looking forward)

    getPhotoByName(me.getGirlfriend()?.getName())
    

    While it is rather 'normal business flow' not to find photo stored into the DB for some person, I used to use pairs like below for some other cases

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);
    

    And don't loathe to type <alt> + <shift> + <j> (generate javadoc in Eclipse) and write three additional words for you public API. This will be more than enough for all but those who don't read documentation.

    /**
     * @return photo or null
     */
    

    or

    /**
     * @return photo, never null
     */
    
  2. This is rather theoretical case and in most cases you should prefer java null safe API (in case it will be released in another 10 years), but NullPointerException is subclass of an Exception. Thus it is a form of Throwable that indicates conditions that a reasonable application might want to catch (javadoc)! To use the first most advantage of exceptions and separate error-handling code from 'regular' code (according to creators of Java) it is appropriate, as for me, to catch NullPointerException.

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }
    

    Questions could arise:

    Q. What if getPhotoDataSource() returns null?
    A. It is up to business logic. If I fail to find a photo album I'll show you no photos. What if appContext is not initialized? This method's business logic puts up with this. If the same logic should be more strict then throwing an exception it is part of the business logic and explicit check for null should be used (case 3). The new Java Null-safe API fits better here to specify selectively what implies and what does not imply to be initialized to be fail-fast in case of programmer errors.

    Q. Redundant code could be executed and unnecessary resources could be grabbed.
    A. It could take place if getPhotoByName() would try to open a database connection, create PreparedStatement and use the person name as an SQL parameter at last. The approach for an unknown question gives an unknown answer (case 1) works here. Before grabbing resources the method should check parameters and return 'unknown' result if needed.

    Q. This approach has a performance penalty due to the try closure opening.
    A. Software should be easy to understand and modify firstly. Only after this, one could think about performance, and only if needed! and where needed! (source), and many others).

    PS. This approach will be as reasonable to use as the separate error-handling code from "regular" code principle is reasonable to use in some place. Consider the next example:

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }
    

    PPS. For those fast to downvote (and not so fast to read documentation) I would like to say that I've never caught a null-pointer exception (NPE) in my life. But this possibility was intentionally designed by the Java creators because NPE is a subclass of Exception. We have a precedent in Java history when ThreadDeath is an Error not because it is actually an application error, but solely because it was not intended to be caught! How much NPE fits to be an Error than ThreadDeath! But it is not.

  3. Check for 'No data' only if business logic implies it.

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }
    

    and

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }
    

    If appContext or dataSource is not initialized unhandled runtime NullPointerException will kill current thread and will be processed by Thread.defaultUncaughtExceptionHandler (for you to define and use your favorite logger or other notification mechanizm). If not set, ThreadGroup#uncaughtException will print stacktrace to system err. One should monitor application error log and open Jira issue for each unhandled exception which in fact is application error. Programmer should fix bug somewhere in initialization stuff.

Upvotes: 80

nilesh
nilesh

Reputation: 14287

With Java 8, you could pass a supplier to a helper method like below,

if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {

}

Above replaces boiler plate code like below,

if(a!=null && a.b()!=null && a.b().c()!=null) {

}

//CommonUtil.java

 public static <T> Optional<T> resolve(Supplier<T> resolver) {
        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        } catch (NullPointerException var2) {
            return Optional.empty();
        }
    }

Upvotes: 4

Binod Pant
Binod Pant

Reputation: 267

One Option you have

  • Use checker framework's @RequiresNonNull on methods. for ex you get this if you call a method annotated as such, with a null argument. It will fail during compile, even before your code runs! since at runtime it will be NullPointerException

    @RequiresNonNull(value = { "#1" })
    static void check( Boolean x) {
        if (x) System.out.println("true");
        else System.out.println("false");
    }
    
    public static void main(String[] args) {
    
    
        check(null);
    
    }
    

gets

[ERROR] found   : null
[ERROR] required: @Initialized @NonNull Boolean
[ERROR] -> [Help 1]

There are other methods like Use Java 8's Optional, Guava Annotations, Null Object pattern etc. Does not matter as long as you obtain your goal of avoiding !=null

Upvotes: 2

yanefedor
yanefedor

Reputation: 2272

All in all to avoid statement

if (object != null) {
    ....
}
  1. since java 7 you can use Objects methods:

    Objects.isNull(object)

    Objects.nonNull(object)

    Objects.requireNonNull(object)

    Objects.equals(object1, object2)

  2. since java 8 you can use Optional class (when to use)

object.ifPresent(obj -> ...); java 8

object.ifPresentOrElse(obj -> ..., () -> ...); java 9

  1. rely on method contract (JSR 305) and use Find Bugs. Mark your code with annotations @javax.annotation.Nullable and @javax.annotation.Nonnnul. Also Preconditions are available.

    Preconditions.checkNotNull(object);

  2. In special cases (for example for Strings and Collections) you can use apache-commons (or Google guava) utility methods:

public static boolean isEmpty(CharSequence cs) //apache CollectionUtils

public static boolean isEmpty(Collection coll) //apache StringUtils

public static boolean isEmpty(Map map) //apache MapUtils

public static boolean isNullOrEmpty(@Nullable String string) //Guava Strings

  1. When you need to assign default value when null use apache commons lang

public static Object defaultIfNull(Object object, Object defaultValue)

Upvotes: 12

Related Questions