7

If I query for an object say for an Animal and the returned object is not null but contains null variables is that wrong? For instance I can call animal.getDeathDate(); and since it's not dead yet it returns null. For a Turtle getFlightSpeed() would return null since it's unable to fly until it has the Turtle rocket pack added. Etc, etc.

I thought that this was a bad way to do things as it will often cause the need for a lot of null checks while calling the methods of the object to verify that they contain non-null values. Are there any links to information about this that could inform both myself and my coworkers further?

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
FooBar
  • 1,663
  • 2
  • 12
  • 19
  • 1
    You may want the Null Object pattern. – SLaks Aug 05 '13 at 13:58
  • I read about the Null Object pattern but I wasn't sure if it addressed objects that had null variables. I thought it was more related to whether a null or an object should be returned from a query method rather than a data object. – FooBar Aug 05 '13 at 14:01
  • 1
    Null Object pattern basically applies to every `null`. Guaranteeing non-null values make code much easier. – zapl Aug 05 '13 at 14:05
  • Ok thanks, I guess I'll redirect to that one, the only problem is there seems to be a lot of debate about it. I was hoping for a more clear cut answer that there was a consensus about. Can you add your comment as an answer? – FooBar Aug 05 '13 at 14:10

9 Answers9

5

null is often ambiguous. Was the field uninitialized yet or it just has no value?

It's often better to have some predefined constant for uninitialized / irrelevant fields.

Even better is to have one class have only one responsibility. Methods like getFlightSpeed() should not be inherited, rather come from implementing an interface (methods like getDeathDate(), though, should have a predefined constant returned when Animal is still alive).

As brought by google-guava docs:

Doug Lea (author of java.util.concurrent package) said that Null s**ks.

Also sir C. A. R. Hoare, inventor of the null reference said: I call it my billion-dollar mistake.

That's some wide shoulder to lay upon.

yair
  • 8,945
  • 4
  • 31
  • 50
  • That is my opinion, I was hoping for some reference material to help support it though. Wasn't able to turn up more than a pretty big debate around the Null Object Pattern through Google. – FooBar Aug 05 '13 at 14:11
  • @FooBar added some reference. – yair Aug 05 '13 at 14:17
  • What do you propose for `getDeathDate()` to return? – Gabe Aug 05 '13 at 14:38
  • @Gabe typically you can declare in `Animal` a `public static final Date NOT_DEAD = // some Date`. In this particular case it might not be applicable if all dates are viable. So I'd use [`Optional`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html). – yair Aug 05 '13 at 16:09
  • I suppose `Optional` would work, though it's hard to see how that's better than `null`, aside from giving you two different types of null values. How do you decide when to use `Optional`? – Gabe Aug 05 '13 at 20:15
  • @Gabe Google's doc on the subject is quite reasonable. `Optional` is better than `null` since it (1) increases readability: it's a clear statement that the field just has no value, which is a viable option; and (2) it's fool-proof: client code has to consider the possibility of no-value. – yair Aug 05 '13 at 20:50
  • @Gabe I use `Optional` in case no-value is an acceptable state and there's no actual dummy value that can represent it. – yair Aug 05 '13 at 20:51
3

Returning null for the death date for an alive animal is perfectly reasonable, but in cases like this I find it better to offer a boolean death check:

public boolean isDead() {
    return deathDate != null;
}

This offers a reasonable way of checking the death-ness of an instance without a clumsy null check of the attribute:

// this is ugly and exposes the choice of the value of the field when alive
if (animal.getDeathDate() != null) {
    // the animal is dead
}

With the isDead() method in place, you would be within your rights to do this:

public Date getDeathDate() {
    if (deathDate == null)
        throw new IllegalStateException("Death has not occurred");
    return deathDate;
}

Regarding the turtle's flying speed, you could apply the same approach, although I would argue that there's a problem in your class design - not all animals fly, so the Animal class shouldn't have a getFlyingSpeed() method.

Instead, use something like this:

interface Flyer {
    Integer getFlightSpeed();
}

class Animal {}

class Turtle extends Animal {}

class Eagle extends Animal implements Flyer {
    public Integer getFlightSpeed() {
         //
    }
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • for the getFlyingSpeed case , instead of implementing an interface , can we have an instance variable in Animal class refer to Flyer type (will have two methods in this interface as can fly and get flying speed )? – Atul Aug 06 '13 at 08:15
  • Having a canFly() is not necessary or desirable, because a) you can use `if (animal instaceof Flyer)`, and b) you need to cast to Flyer anyway to access the Flyer methods, so you already know it's a Flyer because you must do an instance of check before you can cast. – Bohemian Aug 06 '13 at 11:14
1

Null can sometimes be a perfectly reasonable way of representing that an object lacks a particular property.

However, it's useful to allow a single check.

For an array or a List, it's frequently better to have a variable that is always non-null, but can point to an empty list. Otherwise, it becomes necessary to check both that the variable is non-null and that the list has members.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
1

I don't think it's wrong. As an analogy, think of the semantics of NULL in SQL:

A good way to remember what NULL means is to remember that in terms of information, "lack of a value" is not the same thing as "a value of zero"; similarly, "lack of an answer" is not the same thing as "an answer of no".

It's perfectly valid to apply the same logic in Java.

In order to make primitive types nullable, check out the nullable types in C#. It should be easy to implement Nullable as a Java generic.

kol
  • 27,881
  • 12
  • 83
  • 120
1

A major null check rule i have is never to place null instead of a list or an array.

Empty lists and arrays are much better to express what they really are.

mkbrv
  • 407
  • 4
  • 13
0

This is just my opinion, but your example does sound like an anti pattern (as a degenerate null object), as you would need to do null checks on what the methods on the "null object" return. If you don't invoke those getters at all, then your example would be correct.

The idea with null objects is that you don't need to perform null checks at all, so it might work if your getters return other null objects, or the methods use a tell-don't-ask approach (and just return void).

Augusto
  • 28,839
  • 5
  • 58
  • 88
0

Null are perfectly fine, but you should try to avoid them using default values as much as possible

For example empty list should be returned instead of null enum data types should contains UNKNOWN

Above assumption makes life of API consumer easy

in your example I would return null from animal.getDeathDate as I cant think of any suitable default value.

I will provide convenience method animal.isDead returning true/false

For getFlightSpeed() I would return 0 for your case

Mangoose
  • 922
  • 1
  • 9
  • 17
0

Null Object pattern indeed can be used in case of null variables. In case of Turtle.getFlightSpeed() , you can abstract out SPEED concept (may be interface or abstract class) , and have one NULL object implementing "unable to fly" scenario. This will help assigning default behavior to Turtle classes. Returning null in case of animal.getDeathDate() seems fine

Atul
  • 1,560
  • 5
  • 30
  • 75
0

I think that for animal.getDeathDate() returning null if the animal is alive is the correct way to do things. You will always need special code to handle the 2 cases: animal alive, and animal dead, and there is no usefull date you can return if the animal is alive.

For getFlightSpeed() things might be different. I don't know exactly what it returns but let's just for an example imagine it just return the speed as m/s

In that case returning 0(Or an object with the same effect) will make perfect sense, because it does describe the flight speed.

MTilsted
  • 5,425
  • 9
  • 44
  • 76
  • "I think that for animal.getDeathDate() returning null if the animal is alive is the correct way to do things." Well, what if the animal has died, but nobody knows when? – Arnab Datta Nov 09 '15 at 14:14