/**
* Returns the foo with the matching id in this list
*
* @param id the id of the foo to return
* @return the foo with the matching id in this list
*/
public Foo getFoo(int id)
{
for (Foo foo : list)
{
if (foo.getID() == id)
{
return foo;
}
}
return null;
}
Instead of returning null
when foo
is not found, should I throw
an exception
? Does it matter, and is there a "best practices" idiom on the subject? By the way, I know my example is a bit contrived, but I hope you get the idea...
Thanks.
EDIT
Changed code to get Foo
based on id to better illustrate a real-world scenario.
Returning
null
is not only more simple to handle, performs better too. The exceptions must be used to handle exceptional cases.It's best to avoid exceptions if you can, but sometimes you just can't. In this case, what if you had stored
null
in the list? You can't tell the difference between 'found null' and 'could not find what you wanted'.There is a pattern, it's called Option Types and it's used a lot in Scala. You either return a container with the item, or a container of a class that says 'I'm empty'. The wiki article will give a better picture.
You could also have a 'does this exist in the collection?' method which returns a bool, then throw an exception from the above code for if you didn't check first.
And just a comment completely unrelated to your actual question. If you implement equals, it should only return true if the two objects are actually considered equal. Therefore the above code must always return the object you pass into it!
Another point of view I haven't read in the other answers is the following:
Does the
list
containnull
's ofFoo
? If this is the case, one would not know whether the id was found, or whether it was associated withnull
. In this case:SearchResult
, which tells you if the object was found, it's associative id, it's result, or no result if it was not found);existsFoo(int id)
.Each solution has it's own problems, and it depends on the case which to use:
Exception
s are exceptional;SearchResult
, has to be allocated each time you'd like to retry a search. The wrapper can be made mutable, but this introduces a lot of new difficulties and problems;existsFoo
has to search the list which doubles the cost of knowing whether the key exists or not.Generally I can say:
IllegalArgumentException
;SearchResult
;getFoo
only checked whether it's null or not (it exists or not)? Use another method,existsFoo
.While I agree that coding for null is simple and easy boilerplate programmer conditioning, it adds little value for the complexity introduced. Always assuming non-null references makes for cleaner logic with slightly less code -- you still have to test for failure.
The annotation excerpt below will help you to not fall into the old ways...
In this case, since you're defining an accessor, it should return null. If it were another method where this method should guarantee a non-null response, an exception would be more appropriate.
As a side note though, rather than calling the sample method a getter it might be more appropriate to name it something like
Foo findFoo(Foo f)
since you're searching rather than just getting.Returning
null
is fine, if it is documented as a valid result.Another option is the null-object pattern. That is - an instance of
Foo
that doesn't have any data:and return it instead.