Avoiding != null statements

2018-12-31 00:34发布

I use object != null a lot to avoid NullPointerException.

Is there a good alternative to this?

For example:

if (someobject != null) {
    someobject.doCalc();
}

This avoids a NullPointerException, when it is unknown if the object is null or not.

Note that the accepted answer may be out of date, see https://stackoverflow.com/a/2386013/12943 for a more recent approach.

30条回答
孤独总比滥情好
2楼-- · 2018-12-31 00:41

Asking that question points out that you may be interested in error handling strategies. Your team's architect should decide how to work errors. There are several ways to do this:

  1. allow the Exceptions to ripple through - catch them at the 'main loop' or in some other managing routine.

    • check for error conditions and handle them appropriately

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

查看更多
像晚风撩人
3楼-- · 2018-12-31 00:43

In addition to using assert you can use the following:

if (someobject == null) {
    // Handle null here then move on.
}

This is slightly better than:

if (someobject != null) {
    .....
    .....



    .....
}
查看更多
看淡一切
4楼-- · 2018-12-31 00:43

With Java 8 comes the new java.util.Optional class that arguably solves 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 API's contract clearer to the client developer.

They work like that:

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();
   String name = fruit.getName();
}

You can use the map() operator to perform a computation on--or extract a value from--an optional object. orElse() lets you provide a fallback for missing values.

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

Of course, the check for 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.

Optional offers other convenient methods, such as orElse that allow the use of a default value, and ifPresent that works with lambda expressions.

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

查看更多
萌妹纸的霸气范
5楼-- · 2018-12-31 00:45

Just don't ever use null. Don't allow it.

In my classes, most fields and local variables have non-null default values, and I add contract statements (always-on asserts) everywhere in the code to make sure this is being enforced (since it's more succinct, and more expressive than letting it come up as an NPE and then having to resolve the line number, etc.).

Once I adopted this practice, I noticed that the problems seemed to fix themselves. You'd catch things much earlier in the development process just by accident and realize you had a weak spot.. and more importantly.. it helps encapsulate different modules' concerns, different modules can 'trust' each other, and no more littering the code with if = null else constructs!

This is defensive programming and results in much cleaner code in the long run. Always sanitize the data, e.g. here by enforcing rigid standards, and the problems go away.

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

The contracts are like mini-unit tests which are always running, even in production, and when things fail, you know why, rather than a random NPE you have to somehow figure out.

查看更多
爱死公子算了
6楼-- · 2018-12-31 00:46
  • If you consider an object should not be null (or it is a bug) use an assert.
  • If your method doesn't accept null params say it in the javadoc and use an assert.

You have to check for object != null only if you want to handle the case where the object may be null...

There is a proposal to add new annotations in Java7 to help with null / notnull params: http://tech.puredanger.com/java7/#jsr308

查看更多
不再属于我。
7楼-- · 2018-12-31 00:46

Rather than Null Object Pattern -- which has its uses -- you might consider situations where the null object is a bug.

When the exception is thrown, examine the stack trace and work through the bug.

查看更多
登录 后发表回答