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 an Object 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 class Object or class Null you could assign it to an Object variable, sure, but you wouldn't be able to assign it to a String or ArrayList 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 class Null wouldn't have implementations of the methods available on arbitrary subclasses. If null were an object, what would happen if you called null.open("...") on a File reference or null.start() on a Thread? 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 return void, though?) Or maybe they could throw NullObjectExceptions?

    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.

Tags:

Java