Is the null type a reference type?
Dan Smith
daniel.smith at oracle.com
Tue Jan 28 22:54:46 UTC 2025
> On Jan 28, 2025, at 6:24 AM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:
>
> 14.1.1 Switch Blocks requires (T is the type of the selector expression):
> * If a null literal is associated with the switch block, then T is a reference type.
>
> In our case the selector expression has the null type, which can be assigned to any reference type, but it doesn't seem to be a reference type itself.
>
> From this I would conclude that the program is illegal.
See also this assertion from 14.19 about 'synchronized' statements:
"The type of Expression must be a reference type, or a compile-time error occurs."
In this case, 'synchronized (null) { ... }' gets a compiler error.
So, yes, to be consistent, 14.11.1 should explicitly allow 'T' to be a null type.
(I *don't* think it is the intent to reject the switch expression, as evidenced by the reference implementation behavior, and the fact that no rule rejects a switch that leaves out the 'case null'.)
I filed a bug: https://bugs.openjdk.org/browse/JDK-8348901
> Next, lets remove the default case from the same program. Now compilers complain, here's how javac puts it:
>
> X.java:3: error: the switch statement does not cover all possible input values
> switch (null) {
> ^
> 1 error
> So, if the initial program would get the blessing from JLS, then also this case (without default) deserves a second look.
The rules about what counts as exhaustive are laid out in 14.11.1.1. This case is not mentioned, so the spec and implementation are consistent in rejecting it.
I agree it could be worth thinking about this case more, though. (It's not practically useful, but it can be used to explore the underlying rules/intuitions.) JEP 488 enhances exhaustiveness to cover 'case true -> ...; case false -> ...;'. It might make sense to treat this as an additional exhaustiveness refinement to consider.
I actually think that, since exhaustiveness is happy to ignore 'null' in other cases, it might want to treat this switch as exhaustive even if there are *no* case labels.
On the other hand, we typically report a compile-time error if a null literal will trigger a guaranteed NPE (see the 'synchronized' rule above). So maybe it's worth having a special rule that *mandates* a null-handling case?
More information about the compiler-dev
mailing list