In a colon-style switch, case labels do not introduce separate lexical scopes. A local variable declared directly in one case group
remains in scope in later case groups.
Case groups look like separate branches, so readers commonly expect variables declared in one group to belong only to that group. When a later
group accesses such a variable, its actual scope no longer matches the visual structure of the code. Understanding the variable then requires tracing
its declaration and every later case group, which makes the switch harder to read and maintain.
Java’s definite-assignment rules prevent reading a local variable before it has been assigned. This rule does not identify uninitialized reads. It reports variables that are assigned or otherwise accessed across distinct case groups because sharing them obscures their scope.
Consecutive case labels form one case group and do not trigger an issue by themselves. Declarations inside their own block are also excluded because the block limits the variable’s scope.
Give each case group its own variable. For colon-style switches, enclose each group’s statements in a block. Alternatively, use arrow-style rules, which naturally isolate the code for each branch.
void logState(State state) {
switch (state) {
case NEW:
case QUEUED:
String message = "Waiting"; // Noncompliant
log(message);
break;
case RETRY:
message = "Retrying"; // Accessed from this later case group.
log(message);
break;
case FAILED:
message = "Failed"; // Accessed from this later case group.
log(message);
break;
}
}
void logState(State state) {
switch (state) {
case NEW:
case QUEUED: {
String message = "Waiting";
log(message);
break;
}
case RETRY: {
String message = "Retrying";
log(message);
break;
}
case FAILED: {
String message = "Failed";
log(message);
break;
}
}
}
int priority(State state) {
return switch (state) {
case NEW:
int priority = 1; // Noncompliant
yield priority;
case RETRY:
priority = 2; // Accessed from this later case group.
yield priority;
default:
yield 0;
};
}
int priority(State state) {
return switch (state) {
case NEW -> {
int priority = 1;
yield priority;
}
case RETRY -> {
int priority = 2;
yield priority;
}
default -> 0;
};
}
switch
Statementswitch
Expressions