5

I'm developing with java 17 in IntelliJ 2022.2.

In some cases 'switch' expression does not cover all possible input values is shown, but in some not. I'd like to figure out why.

Let's assume that entityType is an enum with 3 values and I'm adding 4th one TYPE_D. So I expect to see 'switch' expression does not cover all possible input values errors where I use this enum in switch.

When it is shown:

public Map<String, String> getRecordDetails() {
    return switch (entityType) {
        case TYPE_A -> Map.of("A","A");
        case TYPE_B -> Map.of("B","B");
        case TYPE_C -> Map.of("C","C");
    };
}

not shown:

public String getRecordDetails() {
    StringBuilder stringBuilder = new StringBuilder();
    switch (entityType) {
        case TYPE_A -> stringBuilder.append("A");
        case TYPE_B -> stringBuilder.append("B");
        case TYPE_C -> stringBuilder.append("C");
    };
    return stringBuilder.toString(); 
}

I see it is related when I do return of switch case, but why it is not shown when I have switch case inside of function's code?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
andriy
  • 4,074
  • 9
  • 44
  • 71
  • 3
    in your first example, nothing is returned for Type_D, in your second example, there is still a default value returned – Stultuske Feb 09 '23 at 09:07
  • what about using default, ex `default -> Map.of();` – Youcef LAIDANI Feb 09 '23 at 09:14
  • 5
    first one is a *switch expression* ([15.28. switch Expressions](https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.28)), second a *switch statement* ([14.11. The switch Statement](https://docs.oracle.com/javase/specs/jls/se19/html/jls-14.html#jls-14.11)), and more [explicitly](https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.28.1-100-B): "*If the type of the selector expression is an enum type, then (i) the set of the case constants associated with the switch block includes every enum constant of the enum type,*" – user16320675 Feb 09 '23 at 09:15
  • 3
    ( in other words, an expression must always return a value [or throw an Exception]; a statement can do nothing ) ( BTW some IDEs show a warning [configurable in Eclipse] for the second case ) – user16320675 Feb 09 '23 at 09:20

1 Answers1

7

When you use a switch as part of a return, it is a switch expression. But if you just put the switch randomly in the middle of a method, it is parsed as a switch statement. These have different rules. Importantly, switch expressions need to be exhaustive.

From the Java Language Specification:

If the type of the selector expression is not an enum type, then there is exactly one default label associated with the switch block.

If the type of the selector expression is an enum type, then (i) the set of the case constants associated with the switch block includes every enum constant of the enum type, and (ii) at most one default label is associated with the switch block.

On the other hand, switch statements do not have this restriction.

Intuitively, expressions have to evaluate to a value, but statements don't have to. Therefore, switch expressions have to cover all cases. If they don't, then there will be situations where it can't evaluate to anything.

In the preview specifications of later versions of Java, the idea of an "exhaustive switch" is more clearly defined, because they now need to support pattern matching among other things.

The switch block of a switch expression or switch statement is exhaustive for a selector expression of type T if either (i) the switch block contains a default switch label, or (ii) the set containing all the unguarded case elements supported by switch labels in the switch block is exhaustive for T, which is specified as follows: [...]

And later,

A switch expression must be exhaustive (14.11.1.1), or a compile-time error occurs.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • thank you! I just not 100% agree with `A switch expression must be exhaustive (14.11.1.1), or a compile-time error occurs.`. That is what I basically want. When I add a new type to the enum, I'd like to compiler warn me that I have to update the switch where this enum is used. – andriy Feb 09 '23 at 09:31