If the only element of the type Void
is null
, and null
is an element of every reference type in Java, why is Void
not considered a subtype of every reference type? Other than legacy, are there reasons why Void
should not be the bottom type in Java?
Note: I'm looking for a design justification (if there is one), not just "because the JLS says so".
Potential use case: empty collections
A typical use case for the bottom type is to type an empty list. Given two unrelated classes A
and B
, consider the following two method signatures.
float processAs(List<? extends A> as) { ... }
float processBs(List<? extends B> bs) { ... }
Note that I made the list parameters 'covariant' using a wildcard. Now, for some list List<C> cs
where C
is any subtype of A
, I'm still able to call processAs(cs)
. (analogously for processBs
) Suppose now that we have an empty list List<...> empty = Collections.emptyList();
. Depending on which type I fill in for the dots, I can call processAs
when it is a subtype of A
or call processBs
when it is a subtype of B
, but not both. Yet, nothing unsafe can happen if I would be able to pass it to both. If Void
was considered the bottom type, we could type it as List<Void>
and I could write processAs(empty)
and processBs(empty)
with no problem.
This would work much like the Nothing
type in Scala, where lists are considered covariant too.
A bit of context
I'm writing a code translator from a language called Nouga (not released yet) to Java. In Nouga, there is a bottom type called nothing
. The Void
type seemed the most appropriate translation for that. Although I can work around the mistranslation of the subtype relation using coercions, it still made me curious whether there are reasons why Void
should not be considered the bottom type.
Possibly related: Why is void not covariant in Java? But this questions seems to be more about a confusion between covariance and contravariance (i.e., the OP uses void
as if it were the top type, not the bottom type).