sealed interface I permits A, B, C { }
final class A implements I { }
final class B implements I { }
record C(int j) implements I { } // Implicitly final
record Box(I i) { }
int testExhaustiveRecordPatterns(Box b) {
return switch (b) { // Exhaustive!
case Box(A a) -> 0;
case Box(B b) -> 1;
case Box(C c) -> 2;
};
}
This is an example that appears in the Java 22 language specification (14.11.1.1).
Subsequently, the specification gives some explanations:
Determining whether this switch block is exhaustive requires the analysis of the combination of the record patterns. The set containing the record pattern
Box(I i)
covers the typeBox
, and so the set containing the patternsBox(A a)
,Box(B b)
, andBox(C c)
can be rewritten to the set containing the patternBox(I i)
. This is because the set containing the patternsA a
,B b
,C c
reduces to the patternI i
(because the same set covers the typeI
), and thus the set containing the patternsBox(A a)
,Box(B b)
,Box(C c)
reduces to the patternBox(I i)
.
However, it's still not detailed enough for me. I can see that these rules should be cited when determining whether the switch block is exhaustive(Some relevant rules):
The switch block of a switch expression or switch statement is exhaustive for a selector expression
e
if one of the following cases applies:• The set containing all the case constants and case patterns appearing in an unguarded case label (collectively known as case elements) associated with the switch block is non-empty and covers the type of the selector expression
e
.
A set of case elements,
P
, covers a typeT
if one of the following cases applies:• The type
T
names an abstract sealed class or sealed interfaceC
and for every permitted direct subclass or subinterfaceD
ofC
, one of the following two conditions holds:
- There is no type that both names
D
and is a subtype ofT
, or- There is a type
U
that both namesD
and is a subtype ofT
, andP
coversU
.•
P
rewrites to a setQ
andQ
coversT
.
A set of case elements,
P
, rewrites to the setQ
, if a subset ofP
reduces to a >patternp
, andQ
consists of the remaining elements ofP
along with the patternp
.A non-empty set of patterns,
RP
, reduces to a single patternrp
if one of the following holds:–
RP
covers some typeU
, andrp
is a type pattern of typeU
.–
RP
consists of record patterns whose types all erase to the same record classR
withk
(k≥1) components and there is a distinguished componentcr
(1≤r≤k) ofR
such that for every other componentci
(1≤i≤k, i≠r) the set containing the component patterns from the record patterns corresponding to componentci
is equivalent to a single patternqi
, the set containing the component patterns from the record patterns corresponding to the componentcr
reduces to a single patternq
, andrp
is the record pattern of typeR
with a pattern list consisting of the patternsq1, ..., qr-1, q, qr+1, ..., qk
.A non-empty set of patterns EP is equivalent to a single pattern
ep
if one of the following holds: ›EP
consists of type patterns whose types all have the same erasureT
, andep
is a type pattern of typeT
. ›EP
consists of record patterns whose types all erase to the same record classR
withk
(k≥1) components and for every record component the set containing the corresponding component patterns from the record patterns is equivalent to a single patternqj
(1≤j≤k), andep
is the record pattern of typeR
with a component pattern list consisting of the component patternsq1,...qk
.
However, I have some difficulty in understanding these rules, especially the parts in bold. For example,What does "from the record patterns corresponding to component ci","from the record patterns corresponding to the component cr" mean?To be more precise, I think I don't quite understand the meaning of "corresponding to" here.
According to the explanations in the specification, I think the sentence "This is because the set containing the patterns A a
, B b
, C c
reduces to the pattern I i
" must have used the rules in the bold part.However, I can't figure out how A a
, B b
,C c
come into being.
Could you please help me analyze the regulations in the specification in combination with the examples?I know it's not an easy task. Thank you for reading and answering.
"Corresponds to" just means what it usually means in English. X "corresponds to" Y means that X matches Y in some way. A pattern corresponds to a record component means that it is trying to match that record component.
Consider the record record R(int x, int y, int z) {}
and the pattern R(int a, int b, int c)
. We can say:
int a
corresponds to the first component x
int b
corresponds to the second component y
int c
corresponds to the third component z
Here I will show that this set of patterns (RP):
Box(A a)
Box(B b)
Box(C c)
reduces to the pattern Box(I i)
("rp").
Applying the quoted rule, RP consists of record patterns that name the record Box
, which only has one component, so k=1. We can show that the only component there is in this record satisfies the conditions of being the "distinguished component" cr. i.e. show that r=1
cr needs to satisfy two conditions:
The first condition is vacuously true since there are no other components.
"The set containing the component patterns from the record patterns corresponding to the component cr" refers to the set:
A a
B b
C c
All of these are "from the record patterns" RP, and they all "correspond to" the only component of the record (which is cr).
Here's another example: the pattern Y y
in the record pattern R(X x, Y y, Z z)
corresponds to the second component of R
.
It is trivial to show that A a
, B b
and C c
covers I
. Therefore I i
is our "q".
Now let's find rp,
rp is the record pattern of type R with a pattern list consisting of the patterns q1, ..., qr-1, q, qr+1, ..., qk
k=1 in this case, so the pattern list only consists of q. We conclude that rp is Box(I i)
.
The first condition for cr is variously true in this case, but let's suppose Box
has two record components both of type I
. And suppose RP has:
Box(A a, I i)
Box(B b, I i)
Box(C c, I i)
Now cr is the first component, and the only ci is the second component. The patterns that "corresponds to" the second component are the three I i
, and obviously they are all equivalent to each other. So this will reduce to Box(I i1, I i2)
.
Finally, let's consider if the switch has the following cases:
Box(A a, A a)
Box(B b, A a)
Box(C c, A a)
Box(A a, B b)
Box(B b, B b)
Box(C c, B b)
Box(A a, C c)
Box(B b, C c)
Box(C c, C c)
This is also exhaustive, but we cannot reduce all 9 patterns all at once, because there is no component that satisfies those two conditions for cr. We can rewrite this set 4 times to reach Box(I i1, I i2)
, each time reducing a subset of the patterns.
First we reduce the first 3 patterns to Box(I i, A a)
, the next 3 patterns to Box(I i, B b)
, and the last three patterns to Box(I i, C c)
. Finally, we reduce Box(I i, A a)
, Box(I i, B b)
, Box(I i, C c)
to Box(I i1, I i2)
.