Switch

So far we have explored decision making using 'if' and 'if-else' statements, however sometimes, it becomes inconvenient to use if / if-else to make a choice, and it can become unreadable. Consider the following example which prints the applicable player name form the 1966 England squad, based on their shirt number:

if (shirtNumber == 1) {
    System.out.println("Banks");
}
else if (shirtNumber == 2) {
    System.out.println("Cohen");
}
else if (shirtNumber == 3) {
    System.out.println("Wilson");
}
//more if-else for shirts 5 to 21
else if (shirtNumber == 22) {
     System.out.println("Eastham");
}

An alternative method of solving the above problem is to use something called a switch statement. This allows us to write code which will execute if a certain 'case' is met. For example, if we were to switch on the shirt number in the above example, in the case that it is a 1, we would print "Banks". The syntax for this would appear as follows:

switch (shirtNumber) {
    case 1:
        System.out.println("Banks");
        break;
    case 2:
        System.out.println("Cohen");
        break;
    case 3:
        System.out.println("Wilson");
        break;
    //... include cases for 4 - 21
    case 22:
        System.out.println("Eastham");
        break;
}

Arguably this may not appear much simpler, but we do not have to repeat the shirtNumber variable multiple times, and this makes it less likely for an error to occur

Fallthrough

One of the key aspects to note in the above example is the use of the break keyword. This tells the computer to stop executing any statements. If we omit it, it will continue executing statements (even in another case) until it reaches the break keyword.

The default clause

Sometimes it is possible that the value we are checking, falls outside the range we have cases for. In the above example a shirt number of 23 (or even 0 or -22) would not print anything, but in this case, we may actually want to take some action - for example, informing the user that they have made a mistake. This can be done by specifying a default operation as follows:

switch (shirtNumber) {
    case 1:
        System.out.println("Banks");
        break;
    //... cases for 2 - 21
    case 22:
        System.out.println("Eastham");
        break;
    default:
        System.out.println("Only 22 England players went to the 1966 world cup");
        break; 
}

If the complete version of the example code was run, and the shirt number was not between 1 and 22, the default clause code would execute

Task

  1. In a new Command line project, create a switch statement that will print out the day of the week based on the number of the day, where Monday is day 1, and Sunday day 7 (as per ISO8601:2004 3.2.2). You should prompt the user to enter a number, and collect it using the Scanner. Example code for collecting integer values using the scanner can be found in the task for the data types tutorial if you cannot remember how to do this
  2. Test the statement by entering values of 3, 6, and 8.
  3. Verify that entering a value of 3 prints 'Wednesday', a value of 6 prints 'Saturday', and nothing is printed if 8 is entered
  4. Modify the code so that if a value other than between 1 and 7 is input an error message is displayed stating that the day of the week is not valid
  5. Based on what you have learned about the break clause, delete existing elements of the code so that it prints out the remaining days of the week, e.g. if the week day number is 5, then Friday, Saturday and Sunday are printed. Ensure that the error message is only displayed when an invalid value is entered.

Matching multiple case values

Sometimes there may be multiple values where we want to execute the same code. Whilst we could repeat code under each case, this is not advised - in fact repeating code is almost always to be avoided where possible, as it provides an additional possible point of error in the programme. A common example of this is calculating the number of days in a month (assuming a non-leap year), rather having seven print statements each printing 31 for the months with 31 days, we can group the cases and make use of fact that without a break statement between them, the code will fall through as described above, e.g.:

switch (monthNum) {
    case 2:
        System.out.println("28 days");
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
        System.out.println("31 days");
        break;
    case 4:
    case 6:
    case 9:
    case 11:
        System.out.println("30 days");
}

Furthermore, we also do not need to place each case statement on a new line, so the code below is functionally identical to that above (though arguably not as readable):

switch (monthNum) {
    case 2:
        System.out.println("28 days");
    case 1: case 3: case 5: case 7: case 8: case 10: case 12:
        System.out.println("31 days");
        break;
    case 4: case 6: case 9: case 11:
        System.out.println("30 days");
}

Task

  1. In a new command line project, write code which will prompt the user for the age of a young person (between the age of 11 and 18, and determine the highest category of film they can view at the cinema unaccompanied. The categories are PG (any age), 12, 15 and 18
  2. Add a default clause stating that they are too young to see a film unaccompanied.
  3. Add an 'if' statement to check if the age entered is over 18. If so, print a message stating that they can see any film they like, but if the value is under 18, ensure the switch statement is executed

Acceptable data types for switch statements

It is important to be aware that in Java, switch statements only work with int, byte, short, char and String data types, as well as Enums which are covered in a later tutorial, so you cannot for example create a switch statement that tests a double value. (Some languages, such as C++ also prohibit the use of Strings in switch statements).