Are null objects equal?
This is really more a philosophical question than a programming question, but one that has been sitting in the back of my mind for a couple of weeks.
If two objects are null, are they equal to each other[0]?
I can see three possible answers:
(a) They're neither equal nor unequal.. because two null objects cannot be compared in the Java world using the good old Object.equals() -- but of course that's only because you cannot call equals() on a null object, so that in itself is not a good enough reason.
(b) They're unequal because we cannot determine any function of equality (usually when we equate objects it's because of some attribute(s)) -- this one breaks down as well, since lack of attributes can be treated as an attribute itself.
(c) They're equal because they lack attributes and all things considered equal, they are identical in the fact that they're null and since Java considers two empty strings as equal (somehow that one is easier to swallow) then it falls within the Java view of the world.
I may be the only person in the world who has a problem just coming up with a simple answer to this one[1], but my gut feeling says it's (c) with a little bit of a mixed in: If the objects are of the same type then they're equal, otherwise it's undeterminable. Which means, two null strings are equal, but a null String object and a null String[] object are not[2].
[0] By equal I mean the Java view of equal, meaning: they're either the same object or their attributes match based on some object-specific function.
[1] Feel free to think me an idiot for even wondering about this.
[2] Of course, there's no way you can tell what an object isn't when it's null.. but it's the intentions that count and this is purely academic anyway.
Comments
Wow, you have lots of time on your hands. :)
Posted by: Anonymous | May 31, 2005 10:28 PM
Well, (a) is how SQL works. In SQL, "null = null" and "null != null" both evaluate to false, which is why you have to use "is null" and "is not null" instead.
Either this is just some arbitrary convention, or there's some well-thought-out set-theoryish reason it is the case. I have no idea which, maybe someone with more knowledge of these matters would be able to find out. If it's the latter, though, it might satisfy your philosophical question.
Posted by: Charles Miller | May 31, 2005 10:28 PM
Terminologically, "Objects" are never null. The reference to an object can be null when it points to nothing but saying that an object itself is "null" in the strict sense has no meaning whatsoever. How do you represent yourself a "null Object"? We can have null references but never null objects per se.
Posted by: Val | May 31, 2005 11:06 PM
Okay, I missed a disclaimer: Let's pretend for sake of discussion that by stating "null object" I mean a null reference.
Posted by: kasia | May 31, 2005 11:09 PM
Why not ask Java itself?
System.out.println(null == null);
Posted by: Tom Klaasen | June 1, 2005 03:48 AM
Cause then it's not an academic exercise! Sheesh.
Posted by: kasia | June 1, 2005 08:54 AM
Are two singularities the same? Is infinity equal to infinity?
Posted by: Philip | June 1, 2005 09:43 AM
In keeping with the "null reference" point, sure, all null references are equal. Behind the scenes, you're secretly playing with pointers. When you have an Object x == null, that's just Object *x == NULL (if you want turn it into C++). And NULL just means zero, or some zero-equivalent on the current machine architecture. That's why NullPointerExceptions always indicate poorly devised code: the developer who wrote the code forgot that they were dealing with pointers by another name.
Posted by: Pat | June 1, 2005 09:45 AM
The Eiffel language has a particularly strong theoretical basis, and in Eiffel the "void" object is defined as the singular instance of the class NONE. The void object is always equal to itself, as specified in section 19.7 of the Eiffel language definition.
The Java language is very similar. Section 3.10.7 of the Java 2 Language Specification says, "The null type has one value, the null reference." Since all null references are references to the same object/value, the "reflexive" rule for the equals() method - x.equals(x) yields true - would tend to suggest that null references are all equal. The only real room for equivocation is that the "reflexive" rule does say "for any non-null reference value," but I would argue that was put in because it's not possible to actually implement equals() for null.
Posted by: Doug | June 1, 2005 12:56 PM
For the mathematically inclined, there are indeed two different cardinalities of infinity. The first kind, called "Aleph_0" (pronounced Aleph NULL - the underscore denotes a subscript), is assigned to infinite sets that can be put on a one-to-one relationship with the positive intergers. That is, in some sense you can assign each object it's own ID number.
Some sets, however, are so big, that no such relationship is possible. This size of set is called "Aleph_1". An intuitive example might be the all the points in a line segment. (It depends on how good your intuition is). You cannot assign all of these points an ID number - you will run out of integers and still have points left over.
The proof is best left to the experts. Don't try this at home.
You could argue that there are many types of singularities as well, but it depends on what you mean by singularity. Those familiar with the calculus of complex numbers should be familiar with the concept of "poles of order N", where N could be some integer. In that sense, not all poles are equal.
Kasia can tell you that not all Poles are equal either.
Neither is Polish beer.
Posted by: Paul | June 1, 2005 01:04 PM
From the set theoretical perspective, comparing NULL objects is meaningless, like dividing by zero. An equivalence relation (of which "is equal to" is a specific instance) is defined as a subset of the Cartesean product of a set with itself (that meet certain other properties). For example, if we have a set of animals living at the farm, the equivalence relation is defined on PAIRs of animals.
The catch is that NULL is technically not part of the set upon which the relation is defined. That is, there is no NULL animal. If you have an animal that is NULL, you technically don't have an animal, thus no relationship is defined. The question has no meaning.
Is NULL equal to Piggy? NULL is not an animal - the question has no meaning.
Is NULL equal to NULL? NULL is not an animal in EITHER case - the question still has no meaning.
Piggy cannot sleep in human's bed.
Neither can NULL.
You might be inclined to say that "is equal" could be overloaded to operate on many different sets, yet the logic will still break down. It's mathematically impossible to construct a logically consistant set that contains "everything". The rules break down, resulting in absurdity.
Before the game begins, you have to establish well defined boundaries.
Posted by: Paul | June 1, 2005 01:17 PM
mu (http://www.catb.org/jargon/html/M/mu.html)
Posted by: Philip | June 1, 2005 04:28 PM
It’s like wondering about the value of 0^0 (zero to the power of zero); is it 1 (as f(x) → x^0 is for all other values of x), or is it undefined? There are consistent arguments for either view.
Personally, I’d take a pragmatic view: it depends on what you’re doing. For the purpose of sorting things, f.ex, I’d consider them equal. But my bias is towards inequality, ie I consider them not equal by default and only take the opposite view after deeming that the circumstances indicate it to be sensible.
Subtle bugs lurk where pieces of code that have contradictory expectations interact, though – f.ex., a piece of code that takes a sorted list as an input vs the code that sorts the list in the first place.
Posted by: Aristotle Pagaltzis | June 1, 2005 06:59 PM
You know, I was going to do the math thing, but figured why take all the fun away from Paul. ;)
I agree with Aristotle\Paul. Generally, I consider NULLs in any sense to be not equal. However, out in the wacky 'real' world, you never know how some business requirement is going to make you bend or break a rule.
I can't think of an example, but I've seen stranger things...
Posted by: pbw | June 2, 2005 08:07 AM
In SQL comparing anything, including NULL, against NULL is not FALSE. But then neither is it TRUE. It's UNKNOWN. WHERE clauses select only when true, not when unknown (or false).
The way I look at UNKNOWN is that it is the set {true, false}. TRUE is the set {true} and FALSE {false}. SQL three value object (3VL) drops out of considering logical operators to act on all combinations of elements.
The way I look at nullable references is that they represent a special case set with cardinality restricted to zero and one.
So if we have a nullable reference to an object fred, then that is {fred}. A null reference is {}. {} does equal {}. However, if we try to force the references to be non-null, then the question is meaningless. Object.equals(null) probably should have been defined to throw an NPE, IMO.
I bet that didn't help.
Posted by: Tom HAwtin | June 3, 2005 01:23 PM