Throw an exception or return null

14,890

Solution 1

About your options, ask yourself if

  1. Is it a good idea to have your program blow up at some point after this method returned an unexpected value (i.e. null)?
  2. What exactly will be hidden if you mask out the null return value?
  3. Is it a good idea to blow up immediately, just because there was a wrong value?

Personally I'd go for option 2 or 3, depending on whether I like the answer to question 2 or 3 better. Option 1 definitely is a bad idea, especially if it's not supposed to happen. If the program throws a NPE way after your function returned, you'll have a hard time figuring out where the null came from. Especially if it happens months after you finished working on this particular function.

If you choose to throw an exception, you immediately see where something went wrong and you can directly go there to figure out why it went wrong. Returning null and checking for it in the calling function could also work, but only if you don't fail silently, but actually do something to handle the problem properly.

Solution 2

I guess what I'm asking is, is this the correct place to throw an exception?

If it were an exceptional situation, then yes. If the possibility of not finding anything that matches the criteria is expected then the situation is not exceptional and you should return null.

Solution 3

Yes, you should throw a RuntimeException to indicate an "exceptional" situation that should not have occurred. IllegalStateException probably fits the bill. Make sure to include a message with any information that will help you find the bug if it is ever thrown.

Solution 4

I believe the correct answer depends on the code that is calling the method. There are two cases:

  1. The calling code is unsure whether the object exists, and is going to have code that will treat the case where it does not exist specially.

  2. The calling code is confident that the object exists, and indeed if it did not exists there would be some other deep problem with the logic and all you can do in this situation is give up and report an error.

In practice, I often implement both with a naming convention to tell them apart:

private MyObject findBlankOrNull() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    return null;
}

private MyObject findBlankOrFail() throws Exception {
    MyObject obj = findBlankOrNull();
    if (obj != null) {
        return obj;
    }
    throw new NoSuchFieldError("No blank piece found!");
}

Notice the OnFail version can alway be constructed calling the other, and then throwing an exception instead of returning the null. Essentially what you are doing is inserting the Exception throw in place of the return null in order to guarantee that no null is returned, and so that you don't need to have any code to test for null at the calling site.

I did a blog post on this topic: Return Null or Exception? that covers it in a little more detail.

Solution 5

May be it's a good idea to use Null Object pattern.

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

So in that case you won't have to use exceptions or return null. You can always return the intended return type object. The trick is when you have nothing to return , instead of returning null or throwing an exception you can return the Null object which is the same type as intended return type.

This documentation has some examples and descriptions. And has a similar case as you, solved by the design pattern.

public class CustomerFactory {

  public static final String[] names = {"Rob", "Joe", "Julie"};

  public static AbstractCustomer getCustomer(String name){   
    for (int i = 0; i < names.length; i++) {
       if (names[i].equalsIgnoreCase(name)){
         return new RealCustomer(name);
       }
    }
    return new NullCustomer();
  }
}
Share:
14,890
Blundell
Author by

Blundell

Software Engineer and Android addict Twitter @blundell_apps StackOverflow Career Profile My Android Developer Blog for Tutorials LinkedIn: http://uk.linkedin.com/in/blundell Google Developer Expert for Android &amp; AndroidThings Author of the book Learning Android Application Testing

Updated on June 04, 2022

Comments

  • Blundell
    Blundell almost 2 years

    If I've got the function below, with two choices

    private MyObject findBlank() {
        for (int i = 0; i < pieces.length; i++) {
            if(pieces[i].isBlank()){
                return pieces[i];
            }
        }
        return null;
    }
    
    private MyObject findBlank() {
        for (int i = 0; i < pieces.length; i++) {
            if(pieces[i].isBlank()){
                return pieces[i];
            }
        }
        throw new NoSuchFieldError("No blank piece found!");
    }
    

    From this method I know that it should always return an object one of the 'pieces' always is isBlank() == true , the return null at the end is just to please the compiler. Since this is the case and my code wouldn't work anyway if it returned null, is this the correct please to throw an exception?

    My options are:

    1. return null and the app will get a NullPointerException in some edge case
    2. return null and wrap the use of the method with (myObject != null) checks
    3. throw an exception which will blow it up at runtime

    I guess what I'm asking is, is this the correct place to throw an exception? i.e. there is nothing I can do about it if it gets into the situation. Is this classed as 'exceptional' or should I null check what my method returns (which makes my code look horrible). If I know it shouldn't return null then I should throw the exception right?

    Also how would I choose what exception, or extend one and throw my own?