5

Speaking of best practices to handle "nulls" in Java(especially "List" returns), is it a good practise to return "Collections.emptyList()" from an entity class's getMethod? or should we keep the entity/data classes/methods neat and clean and always return whatever its value is(even its null) then handle that null somewhere else in the code, for example;

Class Reference{

private Reference reference;

@XmlElement(name = "Reference")
public List<Reference> getReference() {
    if(reference==null){
        return Collections.emptyList();
    }
    return reference;
}

public void setReference(List<Reference> reference) {
    this.reference = reference;
}
}

Or better to handle that null "after" I use a basic get method?

EDIT/WARNING: just for my scenario I noticed this approach crashs my code I dont why, when I later call;

References ref= (References) jaxbUnmarshaller.unmarshal(xmlReader)

I get an unsupported operation exception, but works ok when I clean my getMethod from collections.emtpyList. So caution when using with a @XmlElement tag

Spring
  • 11,333
  • 29
  • 116
  • 185

5 Answers5

3

In general, null and "empty" can have different semantics: null means "it's not there", while "empty" means "it's there, but there's nothing in it".

If your class is such that there is no semantic difference between "not there" and "empty", then returning an empty collection is better: it saves an if statement in all of your callers, making their code look cleaner. Moreover, in this case I would initially set this.reference to Collections.emptyList(), and removed an if from the getter. Of course in this case your setter would need to null-check its argument.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
3

In my experience "Programming by contract" or "Design by contract" (Link) is used when coding Java.
This means, in your example, that if your reference is not set by an outer entity then you simply return a null.

Strike
  • 248
  • 1
  • 8
2

It's indeed good practice to return a non-null collection. It saves every caller from doing

if (list != null) {
    for (Item i : list) {
        ...
    }
}

So the above code is fine. But it would be even finer to disallow any null value in the reference variable. If you have a setter for the list, make it throw an exception if the passed list is null, or transform null into an empty collection. This way, even the code inside your class won't have to bother with the reference variable being null.

If you need to distinguish between null and empty list, consider using Guava's Optional class, which makes things much clearer.

Just a note: since you have a list, the variable should be named references (with a final s), and the accessors should be named getReferences and setReferences.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thank you, all great advices, can we say this null handling in entity class approach is also valid for non-List types like string or integers? – Spring Nov 01 '12 at 12:42
  • You would use Integer instead of int only if you explicitely want the variable to be nullable. Otherwise, using int is a better choice. Regarding String, null is usually used to mean that the attribute isn't set, rather than an empty string. But callers generally don't iterate on String characters. – JB Nizet Nov 01 '12 at 12:46
  • just for my scenario this approach crashs my code I dont why, when I later call (References) jaxbUnmarshaller.unmarshal(xmlReader) .I get an unsupported operation exception, and works when I clean my getMethod from collections.emtpyList.. – Spring Nov 01 '12 at 13:32
1

In general: depends (if you need to be able to distinguish between missing list and empty list).

In the case of XML accessing libraries, there seems to be a convention to always return a mutable list, so that you can update the entity through it. At least that is what all the autogenerated WS-* code does.

For example, to add a reference you would do

x.getReferences().add(someReference);

That would result in an Exception if you returned null.

OTOH, that convention does not have or need a setter for the reference list (you'd just clear the list and add everything instead of setting a new list).

Thilo
  • 257,207
  • 101
  • 511
  • 656
1
private Reference reference = Collections.emptyList();

public List<Reference> getReference() {
    return reference;
}

public void setReference(List<Reference> reference) {
    if(reference==null) 
        reference = Collections.emptyList();
    this.reference = reference;
}
irreputable
  • 44,725
  • 9
  • 65
  • 93