<div dir="ltr"><div dir="ltr"><div dir="ltr"><div>The null handling observed here does seem to be according to JLS. Specifically in §14.30.1 one line reads:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">A type pattern is said to be <span><i>null-matching</i></span> if it is appears
directly in the component pattern list of a record pattern with type <span>R</span>, where the
corresponding record component of <span>R</span> has type <span>U</span>, and the type pattern is
unconditional for the type <span>U</span></blockquote><div><br></div><div>It's a bit unintuitive, but presumably this exception is made in order to allow deconstructing nulls out of records.</div><div><br></div><div>As for the other issue, it seems like the JLS doesn't really care about reachability, but rather whether switch rules dominate each other. The Amount(Number _) rule does not dominate Amount(Object _), even though they end up with the exact same bytecode because the component type is not accounted for.</div><div><br></div><div>Hope this helps!</div><div>- Matias</div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 6 Feb 2026 at 18:23, Red IO <<a href="mailto:redio.development@gmail.com" target="_blank">redio.development@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">This definitely looks wrong. Shouldn't a switch with a pattern matching against null either have a case or throw an exception?<div dir="auto">This behavior seems to differs between a top level match and nested record pattern match. This doesn't seem intuitive nor intentional to me. Even if we say that a _ match arm also includes null which to some extent makes sense because even if it is null it at least has to be of type Number. I would expect a Double _ arm above to not be taken as the information rather it's any subtype of Number is not there.</div><div dir="auto">But last but not least the Object _ shouldn't compile because it is in fact unreachable.</div><div dir="auto"><br></div><div dir="auto">Overall a rather quirky edge case of record pattern matching. </div><div dir="auto">Again I would expect an exception to be thrown because that's the behavior defined in the switch expression. </div><div dir="auto"><br></div><div dir="auto">Great regards </div><div dir="auto">RedIODev </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Feb 6, 2026, 17:00 Cay Horstmann <<a href="mailto:cay.horstmann@gmail.com" target="_blank">cay.horstmann@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Consider this program:<br>
<br>
record Amount(Number n) {}<br>
<br>
Integer value(Amount p) {<br>
return switch (p) {<br>
case Amount(Integer value) -> value;<br>
case Amount(Number _) -> -1;<br>
case Amount(Object _) -> -2;<br>
};<br>
}<br>
<br>
void main() {<br>
IO.println(value(new Amount(null)));<br>
}<br>
<br>
It prints -1.<br>
<br>
I have two questions:<br>
<br>
1. Why does it compile? The case Amount(Object _) does not seem to reachable.<br>
2. Why does null match case Amount(Number _) and not one of the other?<br>
<br>
I tried applying JLS (for Java 25) §14.30, §15.28, and §14.11 but could not figure it out. Where should I look?<br>
<br>
Thanks,<br>
<br>
Cay<br>
<br>
-- <br>
<br>
Cay S. Horstmann | <a href="https://horstmann.com" rel="noreferrer noreferrer" target="_blank">https://horstmann.com</a><br>
<br>
</blockquote></div>
</blockquote></div></div>
</div>