Can you connect two cases of a switch statement using a comma [duplicate]
Asked Answered
F

3

0

I've been working with switch statements in my latest project and wanted to have two possible values execute the same code. So I looked up methods on how do that. Quite the only answer I found looks like this:

switch (element) {
   case hi:
   case hello:
      //do something here
      break;
}

But I experimented a bit more and found that my IDE doesn't complain when I did:

switch (element) {
   case hi, hello:
      //do something here
      break;
}

So I tried it out and found that it works. So I was wondering if there is something wrong with using this method as I found nothing on it online. I would just love to be able to use it as it looks so much cleaner.

Fibula answered 29/10, 2021 at 20:10 Comment(2)
I believe that was added in Java 12. docs.oracle.com/en/java/javase/13/language/…Valley
Yes. Check this out. The example is at the endMashburn
H
2

Your original code segment uses fall-through to give the same response for both cases; some people find this difficult to read and follow. Java 12 gave us two related features that people find help clean up their switch statements, one of which you've discovered here:

  1. cases can be comma separated rather than relying on fall-through
  2. the arrow label can be used instead of the colon and break; commands.

Therefore, if you find yourself not liking fall-through, and not wanting to worry about whether you remembered your break commands, you can write the switch as follows:

switch (element) {
    case hi, hello -> // do something here
    case goodbye, bye -> // do something else here
}

Notice that in this case, we don't have any break statements, but there is no fall-through between the hi case and the bye case; they are separate due to the arrow label.

Heligoland answered 29/10, 2021 at 20:31 Comment(0)
H
7

Recent versions of java (12 and up) have been putting in a ton of work on switch. There are now quite a few forms. Some of these forms have an underlying principle that strongly suggests some new syntactical feature is important, and for consistency's sake, if that feature can also be allowed for the other forms, the other forms are updated too.

History

The original java 1.0 switch is a straight copy from C (which explains their utterly bizarre and silly syntax; it's what C had, and java was designed to be comfortable to C coders. We can whinge about the fact that this means the syntax is daft, but it's hard to deny that the C style syntax, no matter how crazy it seems, has taken over the planet, with C, C#, Java, and Javascript added together taking up a huge chunk of the 'market' so to speak).

It:

  • Required that the thing you switch is on an int and only an int
  • That each case is a specific and constant number (no case 10-100, and definitely no case <5 or case x:).
  • It's a statement (The switch itself doesn't have a value, it's a way to conditionally jump to a statement).
  • Unlike the C version, treating the switch's nature as a weird GOTO-esque construct and thus allowing you to interleave a control structure such as a do/while loop through it is not actually allowed (fortunately, I guess)? - So, Duff's Device is not and has never been legal in java.

Recent updates:

Together with enums: Enums in switches

Java1.5 brought enums, and as enums are intended to replace int constants, they needed to be usable in switches. Given that enum values have an 'ordinal' which is an int, the implementation is trivial: switch (someEnum) { case ENUMVAL: } is light sugar around switch(someEnum.ordinal()) { case 1: }, where 1 is the ordinal value of ENUMVAL.

Only semi-recent: Strings

In JDK7, strings-in-switch support was added. The same principles apply: Only constants, null is not okay - and it's 'fast', in that its implemented as a jump table (contrast to a sequence of if/elseif statements, which requires a comparison for each one. A jump table just jumps, using a single comparison, straight to the right line or to the end if none match.

Now the new stuff (12+): As an expression

These days switch can be an expression. As in, the switch returns a thing. However, in order to make that work, each and every 'path' throughout your switch must return something, and it cannot possibly be the case (heh) that there is a missing case statement; after all, what should the expression resolve to then? Thus, in this 'mode', you must have exhausted all options. Interesting subcase of this is enums, where you can be 'exhaustive', and yet at runtime this can never be guaranteed; what if someone adds a value to an enum and recompiles JUST the enum and drops that in there? Now an erstwhile exhaustive (covers every option) switch no longer is:

int y = switch(textyNumber) {
  case "one": yield 1;
  case "two": yield 2;
  default: yield 0;
};

yield is a new approach here. It's a lot like 'return' - it 'returns' from the switch, returning that value. It is a compiler error if that default clause is missing.

The weirdness with enums means that if you're exhaustive (cover every enum value), it compiles, but if you then add an enum value, do not recompile the code with the switch, and attempt to toss a newly created enum value through, the switch throws a java.lang.IncompatibleClassChangeError. The more you know.

arrow syntax

Because 'yield' is a tad unwieldy and it can be useful to just one-liner the desired expression, similar to how you can write e.g.:

Comparator<String> byLength = (a, b) -> a.length() - b.length();

that same arrow syntax is now legal in switches, and for consistency, it's even legal in statement-form switches:

int x = 1;
int y = switch(x) {
   case 1 -> 2;
   default -> 0;
};

switch (y) {
  case 0 -> System.out.println("Interesting");
}

The arrow prevents fallthrough (it implies break), and takes only one statement. But a whole block also counts as one statement:

switch (y) {
  case 0 -> {
    System.out.println("one");
    System.out.println("two");
  }
  case 1 -> {
    System.out.println("three");
  }
}

would print just 'one', 'two'.

multi-case

Commas can be used to separate values; this is similar to how you can use bars to separate exception types (catch (IOException | SQLException e) { ... }. Applies to all forms.

pattern matching

Now we get to the real intriguing stuff:

record Point(int x, int y) {}

...

Object p = new Point(10, 20);

switch (p) {
case Point(x, y) -> System.out.printf("Point [%d, %d]", x, y);
}

will soon be legal java! Now the thing that follows the 'case' is a 'template'. Can you smash whatever p resolves to into this template? If yes, the case matches, and the variables are filled in for you. This works with 'deconstructable' types (currently: only records; in future any type can provide a deconstructor), as well as an instanceof kinda deal:

Object o = someExpression;

switch (o) {
  case Number n -> System.out.println("is a number. intvalue: " + n.intValue());
  case String s -> System.out.println("is a string: " + s.toLowerCase());
}

I think that covers all the updates that are available for switch up to java v 17 and a bit beyond it, even.

NB: You find this info in extreme detail and as early as you want it by following the appropriate openjdk dev mailing lists. This stuff would be found mostly on amber-dev, with some of the pattern matching stuff found on valhalla-dev due to being closely associated with records, and records overlaps with value types (valhalla = value types for java, amber = general language updates). At java conferences somebody will usually give a breakdown of where this stands, reddit's /r/java tends to post it when someone from the OpenJDK team (for this stuff, you're looking at Brian Goetz generally) posts a major update on how the feature is envisioned / has been implemented. Follow Brian on twitter, that helps too. The release notes, and the umbrella JEP page associated with any new java release should also mention this stuff with links you can then follow.

Homogeneity answered 29/10, 2021 at 20:42 Comment(0)
H
2

Your original code segment uses fall-through to give the same response for both cases; some people find this difficult to read and follow. Java 12 gave us two related features that people find help clean up their switch statements, one of which you've discovered here:

  1. cases can be comma separated rather than relying on fall-through
  2. the arrow label can be used instead of the colon and break; commands.

Therefore, if you find yourself not liking fall-through, and not wanting to worry about whether you remembered your break commands, you can write the switch as follows:

switch (element) {
    case hi, hello -> // do something here
    case goodbye, bye -> // do something else here
}

Notice that in this case, we don't have any break statements, but there is no fall-through between the hi case and the bye case; they are separate due to the arrow label.

Heligoland answered 29/10, 2021 at 20:31 Comment(0)
W
-4

This is not available in Java, However You can do this thing with Kotlin, which is 100% Compatible with Java

Woald answered 29/10, 2021 at 20:29 Comment(1)
... it is, that's why OP is asking. Java's gained more features year over year than kotlin is at this point.Homogeneity

© 2022 - 2024 — McMap. All rights reserved.