开发者

Best practise in catching and throwing nullpointerexception?

开发者 https://www.devze.com 2023-02-05 16:18 出处:网络
It seems like it is not a good idea to catch a nullpointerexc开发者_运维知识库eption. If that\'s the case, why is it thrown by methods? Should it just be caught with Exception?

It seems like it is not a good idea to catch a nullpointerexc开发者_运维知识库eption. If that's the case, why is it thrown by methods? Should it just be caught with Exception?

Also, if I encounter a parameter which is null (can either be primitive type like string or a class with fields), how should I handle it? (assumingly not throw npe)?

Thanks


It is a runtime exception, thus is not intended to be caught deep inside your program code, only [update] at (or close to) the top level or [/update] by the JVM. Since runtime exceptions signal serious problems (typically grave programming errors, configuration/integration problems etc.), it is best to let them propagate to the top, which typically makes the whole thread fail spectacularly. This gives a strong signal that something is wrong and needs to be fixed ASAP.

See also Is Catching a Null Pointer Exception a Code Smell?.

Also, if I encounter a parameter which is null [...], how should I handle it?

It is OK to throw a NPE in general. However, depending on the circumstances, you may also consider IllegalArgumentException, or using an assertion. See also

  • Is it okay to throw NullPointerException programatically ?
  • IllegalArgumentException or NullPointerException for a null parameter?


A nullpointerexception usually indicates a programmer error. You won't catch a null pointer exception if you don't expect such a programmer error. For instance, say you implement a method myMethod with one parameter of type P.

void myMethod(P x)

Let's say you don't expect the parameter x to be null. In this case you might not check for null. Why? because you assume that the programmer who is using your method will use it properly and won't pass null. I'm not saying whether you should or shouldn't check for null in such cases. I'm just trying to answer why sometimes a null pointer exception is thrown by a method and isn't supposed to be caught. Here's why: Your method might throw a null pointer exception because someone didn't use it right (passed null). The programmer who is using your method might know that if the method is being used wrong it might throw a nullpointerexcetption. But even if he uses your method wrong the exception won't be caught because everyone assumes that the method isn't misused.

Your second question: First, a String is an Object, not a primitive type. Second, primitives can't be null (primitives are ints, doubles, floats, chars, booleans and some others). Now, if you encounter a parameter which is null and it shouldn't be null (in other words you received an illegal argument) you have some choices:

  • Throw an IllegalArgumentException indicating the parameter is null and your method expects it not to be null.
  • Don't do anything. Assume your method is being used correctly (in other words, assume no programmer errors).
  • Use assertions: assert(x != null);

I personally am not a fan of defensive programming and usually prefer the second option. But still, if I want to ensure some invariants on my variables I'm using assertions. But these are just my habits and others probably disagree.


This answer may be lengthy but I think it worth it.

It seems like it is not a good idea to catch a nullpointerexception.

You're right, you should not catch NullPointerException, nor any runtime exception.

If that's the case, why is it thrown by methods? Should it just be caught with Exception?

It is used to indicate a programming error was found. These programming errors could and should be fixed with code ( That is, they're preventable )

Also, if I encounter a parameter which is null how should I handle it? [...](assumingly not throw npe)?

It depends on what you want to do with it. For some logic, a null value may be allowed. If that's the case, you validate the presence of null and do something about it, either provide a default value or avoid sending messaged to the null.

For instance. Let's say you have a billing information system, and you have this code where you save the customer information, and you may optionally save customer extra information.

In this case, the optional message may be null, and your code should validate the presence of it.

For instance:

/**
* ...
* @param - OptionalMessage may be null, include anything else you wan to save.
*/
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   message.setHeader( c.name() );
   message.setCustomerInformation( c );
   if( optionalMessage != null ) { // is optional? handle it
      message.add( optionalMessage.status() );
      message.add( optionalMessage.summary() );
      message.add( optionalMessage.message() );
    }
 }

}

You validate the presence of null and document it.

But this same code also has a customer as parameter, in this case you could:

a) Do nothing b) Validate it also c) Throw a different exception according to the level of abstraction at this level.

For instance, the above code, does a) nothing. This will result in a NullPointerException where the code c.name() is invoked, and this should be catched early in the development tests. Also, it should be documented, in the param and the throws in the javadoc.

/**
 * ...
 * @param  c - The customer whose information is to be sent. NotNull 
 * ...
 * @throws NullPointerException if the customer is null
 */
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   ...

If somebody invokes this method with a null, the Npe will indicate they have coded something wrong. Plus, the Npe, will say very quickly what and where the coding error was ( when invoking the sendCustomerInformation with null customer.

option b) Validate it. It may be the case, when you may allow to handle a null customer ( it doesn't make sense but, it is an option )

In this case you may validate it and return prematurely ( in a I'm done fashion )

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  return; // I'm done! } 
   // else 
   SomeMessage message = ... 
   ..
}

Or may create a replacement:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  c = new EmptyCustomer() ;} 
   // else 
   SomeMessage message = ... 
   ..
}

option c) This is similar to a, but, in this case you throw the exception according to the level of abstraction. For instance, if this is going to be shown to the final user in a GUI or something, it may not make sense to just throw the Npe:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // oh oh  something went wrong. 
     log.fatal("Invalid argument on \"sendCustomerInformation\" );
     throw new MyApplicationException("Dear customer, the information yada yaa"); 
   } 
   ...

If this is some sort of invalida state in the app:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // wait a minute, how could... why did.. what?
     throw new IllegalStateException("Hey, I got null on sendCustomerInformation and this shouldn't happen");
   }
   ...

Because maybe the app is responsible to keep that object/parameter in a valid shape.

Conclusion

So it depends on the scenario, but in general terms, a NullPointerException ( and most RuntimeExceptions ) indicate something that could be fixed with code ( that are a programmer mistake ) and you can always do something about it. There are cases where you can't do something about it, the best thing you can do, is to let it pop.

I hope this helps.

See also: Exception other than RuntimeException


Throw an IllegalArgumentException rather than a NP if someone illegally passes Null to your method. That better describes the error.


NPE and RuntimeExceptions in general are mostly thrown when there's a coding error, that's why catching them isn't considered to be a good idea. What should be done instead is fixing the code that can't handle the null input.

Which is the second part of your question, how null input should be handled. It depends entirely on what you're reasonably expecting in your code.

Let's say that you read data from a database table and read a null value from a nullable column, that's definitely not an exceptional case, so your code should handle it as its appropiate from a business point of view (e.g. ignore the entire row, prompt the user to enter a value or just use a dummy value).

However if you're reading a null value from a non-nullable column, say a primary key, you should throw an application-specific exception, which is (hopefully) handled by your application's UI.

So the answer is really as simple as: if null is a value that can happen during normal operation, deal with it accordingly, if not, throw a checked business exception instead of an NPE.


The most probable circumstances under which you might want to catch an NPE is when you are implementing a kind of framework, that is, you do NOT want to terminate your application, but report the error, and you have a way of (sensibly) continue in your application.


To avoid null-checks in your code, in most cases it's appropriate to return a null-object or an empty list/map/set instead of null.

0

精彩评论

暂无评论...
验证码 换一张
取 消