Why is null not an object in Java, if it can be assigned to any reference type?
The easy answer is "because it isn't defined that way in the language".
Conceptually, the distinction is "null is a special Object" versus "null is no object".
Given the special treatment of null, for example, null.equals("something")
will throw an exception, which is not true for someObject.equals(null)
, I'd say the latter view -- null is no object -- is more coherent.
Null could have been defined to be a unique Object
with behavior very similar to null
references. It could be a singleton with a unique name and otherwise uninstantiable; it could compare equal to itself with ==
and unequal to other non-null
objects; it could have a unique class, say Null
.
This is, in fact, a common design pattern known as the null object pattern.
So why isn't it that way?
An
Object
variable can refer to an object of any class. But it doesn't work the other way around. You can't stuff anObject
into any variable you like. I can't write:String str = new Object();
Null objects would still require special language support. If
null
were a singleton object of classObject
or classNull
you could assign it to anObject
variable, sure, but you wouldn't be able to assign it to aString
orArrayList
variable. Java would require different type safety rules, making an exception for this null object so it could be assigned to any type.The null object pattern is typically class-specific. You make a null object for a specific class and then implement sensible behavior for that class's methods on the null object. For example, you could create a "null" list that behaves like an empty list, returning no elements when iterated over and returning a size of
0
when queried.That wouldn't work with a generic null object. A null object of class
Object
or classNull
wouldn't have implementations of the methods available on arbitrary subclasses. Ifnull
were an object, what would happen if you callednull.open("...")
on aFile
reference ornull.start()
on aThread
? Those methods wouldn't be defined.Again, there'd have to be special language support. Maybe those calls could return
null
themselves? (What if they returnvoid
, though?) Or maybe they could throwNullObjectException
s?At some point you're just reinventing null references.
Finally, the simplest answer is: it's not that way because it's another way. Null could be a reference that points nowhere, or it could be a reference to a null object. Even if both were equally good solutions it can't be both. You're asking why it's "A" instead of "B". If it were "B", somebody would be asking why it's not "A".
It could be. In the same way that Object
is a supertype of all (non primitive) types, Null
could be a subtype of all types, with a single instance null
.
Null
would have every possible method, which would all throw NullReferenceException
when called, and every possible field, which would also throw when accessed.
In the end, it would be indistinguishable from the current situation.
Unfortunately, in many tutorials, books and other resources about Java, the terms "object" and "variable" are used in a sloppy way, which can lead to confusion similar to what you describe in your question.
For example, look at this line of code:
String message = "Hello World";
People will often say "I have a String
object named message
here with the value "Hello World
". This is wrong and it makes beginners think that objects and variables are the same thing, and that objects have names.
Accurate would be: "I have a variable named message
here which is a reference to a String
object with the value "Hello World"
.
Variables and objects are not the same thing. A variable* is not an object, it's a reference to an object (it's a pointer to an object somewhere in memory).
Variables have names. In the code above, there is a variable named message
. Objects do not have names.
There is also not a one-to-one correspondence between variables and objects. Multiple variables may refer to the same object.
The value null
is a special value that you can assign to variables* that means "this variable refers to no object". It's just like a null pointer in languages such as C and C++.
It doesn't really make sense to talk about null
being an object. It's not an object, it's a special reference value to make variables refer to "no object".
If null can be assigned to any Object type
This is why I suspect you're confused about the difference between objects and variables: you do not assign null
to an object, but to a variable (of "any object type" which is the same as "of a non-primitive type").
*: we're talking about variables of non-primitive types here
For a more advanced understanding:
The value null
has a bit of a bad reputation (it's the cause of many bugs). You might want to use java.util.Optional
to help prevent some of the problems that null
causes.
See also the null object pattern, which is a design pattern about the idea of having a special object that represents "the empty value". This might be useful in special situations.