JavaRush /Java Blog /Random EN /Switch statement in Java

Switch statement in Java

Published in the Random EN group
Imagine that you are standing at a fork, like a hero from a famous painting. If you go to the left, you will lose your horse; if you go to the right, you will gain knowledge. How to program such a situation? You most likely already know that we make such a choice using the if-then and if-then-else constructs .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
What if there are not two such tracks, but 10? Is there a path “to the right”, “a little to the left”, “a little more to the left” and so on, in the amount of 10 pieces? Imagine how your if-then-else code will grow in this version!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
So, you don’t have one fork of conditions, but several, say, 10 (the important thing here is that the number of forks is limited). For such situations, there is a special selection operator - switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
The execution order in the statement is as follows:
  • The SelectionExpression is evaluated. Next, the switch statement compares the resulting expression with the next Value (in the order listed).
  • If the SelectExpression matches the Value, then the code following the colon is executed.
  • If the break construct is encountered , then control is transferred outside the switch command.
  • If no matches between ExpressionForSelection and Values ​​are found, then control is transferred to the DefaultSelectionCode.
Important points
  • The SelectionExpression type for a switch selection statement in Java must be one of the following:

    • byte , short , char , int .
    • Their wrappers are Byte , Short , Character , Integer .
    • String (since Java 7).
    • Enumeration ( Enum ).
  • The default block is optional, then if the SelectionExpression and Values ​​do not match, no action will be performed.
  • break is optional; if it is not present, the code will continue executing (ignoring further comparisons of values ​​in case blocks) until the first breakswitch statement encountered or until the end.
  • if it is necessary to execute the same code for several selection options, to avoid duplication we indicate several corresponding values ​​in front of it in consecutive case blocks .

Let's move on to the practice of using the switch statement in Java

Don't worry, we're done with the theory, and after further examples everything will become much clearer. So let's get started. Let's look at an example from astronomy about the planets of the solar system. In accordance with the latest international regulations, we will exclude Pluto (due to the properties of its orbit). Let us remember that our planets are located from the Sun in the following sequence: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus and Neptune. Let's create a Java method that receives as input the serial number of the planet (relative to the distance from the Sun), and as an output it gives the main composition of the atmosphere of this planet in the form of a List <String> . Let me remind you that some planets have a similar atmosphere composition. Thus, Venus and Mars contain mainly carbon dioxide, Jupiter and Saturn consist of hydrogen and helium, and Uranus and Neptune, in addition to the last pair of gases, also have methane. Our function:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
Please note: we compared the same code to planets with identical atmospheric compositions. And we did this by using consecutive case constructions . So, if we want to get the composition of the atmosphere of our home planet, we call our method with parameter 3:
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Experiment with break What happens if we remove all break statements ? Let's try it in practice:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
If we print out the result of the method System.out.println(getPlanetAtmosphere(3)), then our home planet will not be so suitable for life. Or suitable? Judge for yourself: [Carbon dioxide, Nitrogen, Oxygen, Hydrogen, Helium, Methane, Hydrogen, Helium], Why did this happen? The program executed all cases after the first match and until the end of the switch block.

Excessive optimization break

Note that we can improve the method with a different arrangement of break directives and selection options
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
Looks shorter, doesn't it? We reduced the total number of statements by playing with case order and regrouping. Now each type of gas is added to the list in only one line of code. The listing of the last example of the method is shown only to demonstrate the work; it is highly not recommended to write in such a style. If the author (and even more so third-party programmers) of similar code has to maintain it, then it will be very difficult to restore the logic for the formation of selection blocks and executable code for the java switch statement.

Differences from if

While the if and switch statements are similar in appearance , do not forget that the multiple choice operator switch bases the choice of execution options on a SPECIFIC VALUE, whereas in if. can be any logical expression. Take this fact into account when designing your code. Let's take a closer look at the innovations for switch in different versions of Java.

Switch in Java 7

Before Java 7, byte, short, char and int primitives could be used as the value for a switch. There was also support for enum and wrappers of the primitive types listed above: Character, Byte, Short, and Integer. But often we need to find the value of a java switch string! This is what it would look like in Java 6:
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
And enum:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
But starting with Java 7, it was possible to use the String type as a value for a switch:
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
Despite the new features, the approach using enum is more flexible and is recommended for use: we can reuse this enum many times.

Switch in Java 12

Java 12 has improved Switch expressions for pattern matching. If we use Switch as in the example above, to set the value of some variable, we had to calculate the value and assign it to the given variable, and then use break:
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
But thanks to the capabilities of Java 12, we can rewrite this expression as follows:
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Let's go over the changes a little:
  1. If previously we set a variable value inside case blocks, since the switch statement itself could not return anything, now we have such an opportunity, and we directly return the value using switch.

  2. Previously, we could no longer have anything to the right of break, but now we use it as a return statement to return the value of our switch. Colon marks mark the entry point into a statement block. That is, from that point the execution of all the code below begins, even when another label is encountered.

    The result is an end-to-end transition from mark to mark, which is also called fall -through.

Switch statement in Java - 2To complete such a pass, you must either go through all the elements completely, or use break or return. The innovation in java 12 gives us the ability to use the lambda operator, which in turn ensures that only the code to the right of it will be executed. Without any "failure". What will the previous example look like in this case:
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
The code has become much simpler, hasn't it? And one more thing: the lambda operator can also serve as a typical analogue of a colon, after which there is a whole block with some operations:
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
Well, what if for some cases the return value is the same? It turns out that we actually have the same cases for some different values. Here's how this could be shortened using new features in Java 12:
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Switch in Java 13

In Java 13, the way a switch returns a value has changed. If in java 12 we wrote the return value after break, which served as a return for us for the switch block, now we will return the value using the word yield . Let's look:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
At the same time, code written in java 12 using break to return will not compile (( Switch statement in Java - 3Break will be used, but in situations where we do not need to return anything.

Total

  • Use the case statement when there are more than two branches to avoid cluttering your code with if structures.
  • Don't forget to end the logical block of each branch corresponding to a specific value (case block) with a break call .
  • In addition to some primitive types, the switch statement can also use Enum and String types as expressions .
  • Remember the default block - use it to handle unplanned selection values.
  • To optimize performance, move the code branches with the most common choices to the beginning of the switch block.
  • Don’t get carried away with “optimization” by removing the break at the end of the case selection block - such code is difficult to understand, and, as a result, difficult to maintain during its development.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION