I have a java enum:
public enum PaxosRole {
FOLLOWER,
RECOVERER,
LEADER
}
I wish to use it in a record such as:
public record PaxosEvent(PaxosRole role, PaxosMessage message) {}
When I try to pattern match it with:
final var paxosEvent = new PaxosEvent(role, msg);
switch (paxosEvent){
case PaxosEvent(PaxosRole.FOLLOWER, var msg) -> {
// do something
}
case PaxosEvent(PaxosRole.RECOVERER, var msg) -> {
// do something else
}
case PaxosEvent(PaxosRole.LEADER, var msg) -> {
// do something distinct
}
}
My IDE says Unknown class for the enum in the pattern matches.
Trying to swap the enum for a complex sealed class:
sealed interface PaxosRole {
record Follower() implements PaxosRole {};
record Recoverer() implements PaxosRole {};
record Leader() implements PaxosRole {};
Follower FOLLOWER = new Follower();
Recoverer RECOVERER = new Recoverer();
Leader LEADER = new Leader();
}
Then the following does not work:
switch (paxosEvent){
case PaxosEvent(PaxosRole.Follower _, var msg) -> {
throw new AssertionError("follower role not implemented");
}
case PaxosEvent(PaxosRole.Recoverer _, var msg) -> {
throw new AssertionError("follower role not implemented");
}
case PaxosEvent(PaxosRole.Leader _, var msg) -> {
throw new AssertionError("follower role not implemented");
}
}
My IDE says that only the first branch will match; the other two branches are the same class. I am guessing it thinks all are of type PaxosRole. Even if it was to work, it looks pretty verbose.
I can use a with to check the enum:
switch (paxosEvent){
case PaxosEvent(var role, var m) when role.equals(PaxosRole.FOLLOWER)-> {
throw new AssertionError("follower role not implemented");
}
case PaxosEvent(var role, var m) when role.equals(PaxosRole.RECOVERER)-> {
throw new AssertionError("follower role not implemented");
}
case PaxosEvent(var role, var m) when role.equals(PaxosRole.LEADER)-> {
throw new AssertionError("follower role not implemented");
}
}
Yet my IDE then tells me that the match is not exhaustive. So, it wants me to add a default branch. Yet it is exhaustive; all three enums are covered in the with statements.
Is there a way to use a simple enum in a switch in Java 22 without a default and without being so verbose?
Mixing value cases and record/type patterns is not supported yet.
Your work-around
does work with
javac; any problems in your IDE are related to the IDE.Alternatively, you can use record patterns instead of type patterns:
But there is no need for pattern matching at all with your original definition of
PaxosRoleas anenumtype. You could simply useThis would require accessing
paxosEvent.message()manually when needed. If you really need to avoid that, you can nest switch statements:This can still be quite compact. E.g. as an expression:
And pattern matching will evolve. Patterns like in your first attempt might be possible in the future…