Alternatives to returning NULL
/**
* 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 开发者_JAVA技巧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.
I'd say it depends on the semantics of your method.
Will foo
be almost always found in the list? (for example, if it is a cache that holds a finite amount of objects). If so, then not being found might mean something has gone wrong -- some app initialization failed, for example, or the key is invalid -- and an exception might be justifiable.
In most circumstances, however, I'd return null
. Maybe the client knows the object might not be there and has coded logic to handle that case; if you used an exception, that code would be much harder to read, understand, and maintain.
Some APIs actually provide two methods: a find
method that may return null, and a get
or load
method that throws an exception.
Hmmm... when in doubt, err in favor of null :)
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:
public class Foo {
public static final Foo NULL_FOO = new Foo();
}
and return it instead.
I prefer returning null
. This is a perfectly fine result to return from a method, and your code that calls the method should handle null values appropriately. That might mean throwing an exception in your calling code, but I wouldn't do it in this method.
This way, if someone else wants to call your method down the line, they can handle null values differently than you if they choose. If you threw and exception it could potentially force another programmer to alter their code in a way different than what they intended.
Of course, there are some cases where it would make sense to throw an exception if something is null (like, a connection object or something like that, that you actually need to have a value and if you don't then that means something is wrong). But, as a rule of thumb, you should be fine returning null in most 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!
Best pactice would be to say in the Javadoc that null
is return when no match is found.
Another approach might be to return a List of matches which could be empty (and could have more than one) However I don't like this approach.
Another approach might be to return a NULL_FOO of type Foo value.
I would prefer to just return null.
One way around this is to look at what are you going to do with the value and enrich the function so that the returned value is used in the method and not returned. e.g. if you are going to call a method with the value, just call it in the function which avoids the need to return anything.
This is an old question but I didn't find guava's Optional class mentioned here and also JDK's Optional (from Java 8) which serves the same purpose and has more functionality.
This article is a good overview on the reasons for using guava's Optional. I highly recommend reading it.
Here's an excerpt:
What's the point?
Besides the increase in readability that comes from giving null a name, the biggest advantage of Optional is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, we don't think it addresses the issue nearly as well.
This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves for their code to compile.
My personal opinion, if that matters at all, is that returning null is not so terrible in an already verbose language like Java. The signature of the method sometimes screams that there can be some sort of null kind of result and using Optional doesn't add anything in terms of semantics anyway. For example:
public Point2D intersect(Line line)
Or in a method that looks up a value in a map by key.
If one calls such a method and performs a null check on the result, it's pretty obvious what is going on (checking for parallel lines or key not found). I would favor returning null lest I bloat my code.
I would always document it in the javadoc though.
majory it depends on the scenarios. If your app is itself producer and consumer of this method then it is completly upto you to decide what to do, Else you need to decide based on usage of the method and Client needs.
Returning null
is perfectly acceptable. I would go the extra couple dozen keystrokes and document the possibility of returning null
in the JavaDoc.
Throwing checked exception means you have to try/catch or re-throw that exception everywhere your method gets called. An unchecked exception, especially anything other than an NPE, is going to catch people by surprise.
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.
I think it's a matter of taste and in this case it also depends on if the list may contain null values. If the list may contain null values, null would also be a valid method argument and you would need to distinguish between returning null (e.g. null was passed, found and returned) or telling the method caller that the passed null value was not found.
This might not answer your question directly but it comes from a few remarks I've gotten from Stackoverflow members on similar topics.
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..."
From what I gather, Exceptions should be thrown from a method when the Exception concerns a parameter given to the method. For example, a method accepting File instances would throw a NullPointerException or an IOException. This is following the idea that there's a contract between the caller and callee that the caller should sent valid objects and take care of them if they're invalid.
Also, you need to decide whether to handle pre- and postconditions. You can place a guard at the beginning of a method to handle parameters and this would save quite a bit of code. However, some view this as an incorrect approach in that some validation, say in a UI, should be done beforehand.
To finish off, it's perfectly valid to return a null object if the intent is to retrieve a a single instance. This is to paraphrase that an object was not found or doesn't exist. When it comes to groups of objects I think the convention is simply to return an empty Collection/List.
I'd say it depends on your app and how the method will be used.
- If you expect a "not found" result happen frequently enough that it could negatively affect performance*, then return null, and check for it in the caller.
- If "not found" results will be relatively rare or will cause you app give up on the request, then throwing an exception would be fine. Exceptions could make your code easier to read, as you can then guarantee a successful return will produce an object, so you don't have to null-check it.
I subscribe to the opinion that exceptions should be used for exceptional conditions, which is a superset of error conditions. I also have adopted Spring/Hibernate's preference for unchecked exceptions, which avoids burdensome try/catch logic.
* There is not much performance overhead from using exceptions vs. returning null. I just did a quick test, it takes 4ms to call a method a million times that returns null, and only 535ms to another method million times that throws an exception.
Another point of view I haven't read in the other answers is the following:
Does the list
contain null
's of Foo
? If this is the case, one would not know whether the id was found, or whether it was associated with null
. In this case:
- Throw an exception that the list is not found;
- Wrap the result in another object (e.g. a
SearchResult
, which tells you if the object was found, it's associative id, it's result, or no result if it was not found); - Create the method
existsFoo(int id)
.
Each solution has it's own problems, and it depends on the case which to use:
- As others noted,
Exception
s are exceptional; - A wrapper,
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:
- Is an ID not being found exceptional? Use
IllegalArgumentException
; - Is the result passed to other classes, used as an object? Use a wrapper, e.g.
SearchResult
; - Is with
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...
Use @Nullable
To eliminate
NullPointerExceptions
in your codebase, you must be disciplined about null references. We've been successful at this by following and enforcing a simple rule:Every parameter is non-null unless explicitly specified.
The Guava: Google Core Libraries for Java and JSR-305 have simple APIs to get a nulls under control. Preconditions.checkNotNull can be used to fast-fail if a null reference is found, and
@Nullable
can be used to annotate a parameter that permits the null value:import static com.google.common.base.Preconditions.checkNotNull; import static javax.annotation.Nullable; public class Person { ... public Person(String firstName, String lastName, @Nullable Phone phone) { this.firstName = checkNotNull(firstName, "firstName"); this.lastName = checkNotNull(lastName, "lastName"); this.phone = phone; }
If null is permissible by your class, you can annotate the field or parameter with @Nullable ... using any @Nullable annotation, like edu.umd.cs.findbugs.annotations.Nullable or javax.annotation.Nullable.
精彩评论