0

Imagine a method which takes an object as a parameter and check with a for each loop for lets say some other values inside of some collection, which can be found/filtered according to the passed in argument. Is it a good practice to check at the beginning of the function for null pointer and return immediately an empty collection or null pointer, or is it better to just leave out the null pointer checking, as for each loop takes care of it, but the function will need more time to execute (because of the whole for each iteration). And lets say that this collection isn't big (not that much time consuming).

 public ArrayList<Foo> find(Bar bar) {  
        if (bar == null) { // get rid of these part?
            return null;   //
        }                  //  

        ArrayList<Foo> foos = new ArrayList<Foo>();
        for (Foo f: Foo.values()) {
            if (f.someBarCollection.contains(bar)) {
                foos.add(f);
            }
        }

        return foos;
 }

I think It's better to check for null and return immediatelly if you know that It's a waste of time doing any further actions, because you know they're not needed. So I'm favouring semantics at the expense of a shorter code, to make things unambigous.

EDIT: Let me elaborate a bit further. The result of the function is the same with OR without the null checking part. The question is just, should I check It anyway, just for the sake of better expression (and a bit of performance gain, but this is not a problem), but the code will be longer (because of the added checking)?

3
  • 2
    1. return the interface not the implementation type 2. use the assert keyword 3. return an empty collection, not null. That's said: what if the collection contains null ? Commented Feb 9, 2015 at 15:46
  • We can assume the collection doesn't contain null. Commented Feb 9, 2015 at 16:13
  • 1
    Use the assert keyword, only if it is incorrect for the caller to pass a null. If it is valid for the caller to pass a null, handle it as you did (except return an empty collection). Commented Feb 9, 2015 at 16:40

5 Answers 5

5

It depends

Depending on your API, you can do the following when the parameter received has a null value:

  • Throw an exception. Probably IllegalArgumentException or a custom exception describing the reasons on this bad argument.
  • Return a null value and let the client handle the result in the rest of the code.
  • Return an empty result. In case of List (not ArrayList), you could return Collections#emptyList.

Either option you use for your API/methods, make sure to document it properly in the javadoc.

Sign up to request clarification or add additional context in comments.

5 Comments

If OP want to throw an Exception, then he could use Guava: Preconditions#checkNotNull.
@Tom that depends on implementation. It depends if you use Guava in your projects (I don't use it on mine yet).
the collection could actually contain null ?
@guido again: it depends. But that will be an odd result, don't you think?
(About Guava) Well, this is clear. If you don't use it (yet), then you can't use one of its features :D. But OP could consider using it.
1

Wether you check or not is more a matter of taste than of performance. However, to make stuff easier on your clients, you should not return null, but an empty collection.

Depending on the use case, you could also raise an exception (if nulls should not be permitted) and/or annotate the bar argument with @NonNull to allow use of pluggable checkers.

Comments

1

It depends on expected bar value. If null is allowable value for bar you decision is good. Otherwise it's better to throw exception.

2 Comments

Yes, null is allowable, I just return sooner if It is, that's all!
@user2340939 this also depends. This is other criteria: code is more understandable when it has a single point of return, and you can achieve it easily by using if (validArguments(arg1, arg2 ...)) { /* current implementation of method */ } //here throw the exception or return whatever you want/need.
0

One thing to consider is future-proofing.

If you can imagine a time when the collection legally contains(null) then either let it run through (and return an empty collection) or throw an exception (probably IllegalArgumentException). Throwing an exception will mean that change won't affect the behavior of existing legal code.

Unless you considered returning null for 'empty' when bar!=null (not normally recommended) it's a little inconsistent to return it for bar==null.

Quite rightly most of the other posts discourage null for 'empty'. The only reason to use it would be performance:

//WARNING - THIS CODE IS NOT FIRST CHOICE
public ArrayList<Foo> find(Bar bar) {  
        ArrayList<Foo> foos = null;
        for (Foo f: Foo.values()) {
            if (f.someBarCollection.contains(bar)) {
                if(foos==null){
                    foos=new ArrayList<Foo>();
                }
                foos.add(f);
            }
        }
        return foos;
 }

Collections.emptyList() is valuable but any calling code that thinks it can modify the list will get a nasty surprise of UnsupportedOperationException. So replacing null with 'empty' can risk exchanging NullPointerException for (possibly a less frequent and harder to spot) UnsupportedOperationException. Not as much progress as we'd like.

The next alternative of returning a local ArrayList is frightening:

//DANGER - CODING HORROR!

static final sEmpty=new ArrayList<Foo>();

public ArrayList<Foo> find(Bar bar) {  
        ArrayList<Foo> foos = null;
        for (Foo f: Foo.values()) {
            if (f.someBarCollection.contains(bar)) {
                if(foos==null){
                    foos=new ArrayList<Foo>();
                }
                foos.add(f);
            }
        }
        return foos==null?sEmpty:foos;
 }

In this case ignorant code might add elements to a supposedly empty ArrayList and cause them to be returned by subsequent calls to find(). A great way to spend a day is finding that one!

Sadly, it seems we're as far from Java implementing C++ style const to differentiate mutable and immutable references than ever. So in at least some cases you're left with returning small junky objects or null for 'empty'.

At the end of the day the Java libraries take the attitude the creating and destroying lots of small objects is an acceptable overhead for simplicity (look at 'boxed' primitives like Integer). Many modern JVMs have generational garbage collectors designed to harmonise with that style.

So if you're undecided about 'accepting' null:

public ArrayList<Foo> find(Bar bar) {  
        if(bar==null){
            throw new IllegalArgumentException("bar==null");
        }
        ArrayList<Foo> foos = new ArrayList<Foo>();
        for (Foo f: Foo.values()) {
            if (f.someBarCollection.contains(bar)) {
                foos.add(f);
            }
        }
        return foos;
 }

Otherwise go with the flow:

public ArrayList<Foo> find(Bar bar) {  
        ArrayList<Foo> foos = new ArrayList<Foo>();
        for (Foo f: Foo.values()) {
            if (f.someBarCollection.contains(bar)) {
                foos.add(f);
            }
        }
        return foos;
 }

Only consider alternatives if this method is a proven bottle-neck.

5 Comments

Ok, you made a great point. But if you want the null value to be invalid for the functions argument and you decide to throw exception in this case, wouldn't it become unreadable because every function which contained a nullable parameter, would contain exception code in its signature and at the beginning of its body? Or is this extra code worth the benefits you get from it?
It is certainly impractical to put such code at the front of every method. However it can pay big dividends in a consumer API. My point is that throwing an exception would 'reserve' you the scope to extend the functionality at a later date. But doing something innocuous like returning null establishes a behaviour that someone somewhere might be relying on (whether that's wise or not).
At least in situations where there would be no harm if invalid parameter (null) was specified, but the return value would be non-null (empty collection), we can get rid of exception handling, because the function actually gives meaningful return value, even with an unmeaningfully parameter value (e.g. you want to get all of the children of a tree node, but if you specify null as a tree node object, you get an empty collection, as in "null tree node has no children"). What's your point of view on these situations?
@user2340939 I tend to agree in this case. But it's sometimes the cases where logically invalid arguments will return apparently meaningful results that you should put in validation guards.
Exactly, because here the caller might not have intended to pass null object to the function in the first place, which means he would've mistakenly thought that there was no problem with his calling code, although there was.
0

That depends how often (and whether at all) you expect null to be passed to this method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.