The switch statement

Figure 188. Better: Using switch Slide presentation Create comment in forum
...
switch(number) {
    case 1: System.out.println("Monday"); break;
    case 2: System.out.println("Tuesday"); break;
    case 3: System.out.println("Wednesday"); break;
    case 4: System.out.println("Thursday"); break;
    case 5: System.out.println("Friday"); break;
    case 6: System.out.println("Saturday"); break;
    case 7: System.out.println("Sunday"); break;

    default: System.out.println("Invalid number " + number); break;
} ...
Enter a weekday number (1=Monday, 2=Tuesday,...) : 6
Saturday

Figure 189. switch Syntax Slide presentation Create comment in forum
switch(expression) {
[case value_1 :
    [statement]*
    [break;] ]
[case value_2 :
    [statement]*
    [break;] ]
  ...
[case value_n :
    [statement]*
    [break;] ]
[default:
    [statement]*
    [break;] ]
}

exercise No. 60

Why break? Create comment in forum

Q:

Do we need break statements in Figure 188, “Better: Using switch? Rewrite Figure 187, “Implementing number to day's names ” replacing all conditions by switch / case statements without using break. What do you observe on execution?

A:

Figure 187, “Implementing number to day's names ” can be rewritten as:

try (final Scanner scan = new Scanner(System.in)) {
    System.out.print("Enter a weekday number (1=Monday, 2=Tuesday,...) : ");
    final int number = scan.nextInt();
    switch(number) {
        case 7: System.out.println("Sunday");
        case 1: System.out.println("Monday");
        case 2: System.out.println("Tuesday");
        case 3: System.out.println("Wednesday");
        case 4: System.out.println("Thursday");
        case 5: System.out.println("Friday");
        case 6: System.out.println("Saturday");
        default: System.out.println("Invalid number " + number);
    }
}

Entering a day's number 5 yields:

Enter a weekday number (1=Monday, 2=Tuesday,...) : 5
Friday
Saturday
Sunday
Invalid number 5

So the break statements effectively prohibit fall-through towards subsequent case labels. Moving 7 / Sunday to the beginning this becomes even clearer:

...
switch(number) {
   case 7: System.out.println("Sunday");
   case 1: System.out.println("Monday");
   case 2: System.out.println("Tuesday");
   case 3: System.out.println("Wednesday");
   case 4: System.out.println("Thursday");
   case 5: System.out.println("Friday");
   case 6: System.out.println("Saturday");
   default: System.out.println("Invalid number " + number);
} ...

This time entering number 5 again our output no longer contains "Sunday":

Enter a weekday number (1=Monday, 2=Tuesday,...) : 5
Friday
Saturday
Invalid number 5

Thus fall-through does not depend on numerical case label ordering but solely on their order of appearance within code.

exercise No. 61

Extending to month days Create comment in forum

Q:

Consider May 2017:

Monday Tuesday Wednesday Thursday Friday Saturday Sunday
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

Write an application converting a given day's number within May 2017 (this may be generalized to arbitrary months) to its name e.g.:

Enter a day's number:>23
Tuesday

Tip

The modulo operator % is your friend.

A:

With respect to Figure 188, “Better: Using switch a small modification is being required

...
switch(day % 7) {
   case 1: System.out.println("Monday"); break;
   case 2: System.out.println("Tuesday"); break;
...
Figure 190. Switching on strings Slide presentation Create comment in forum
String month, season;  
...
// Since Java 7: String based case labels
switch(month) {
    case "March": case "April": case "May":
       season = "Spring"; break;

    case "June": case "July": case "August":
        season = "Summer"; break;

    case "September": case "October": case "November":
       season = "Autumn"; break;

    case "December": case "January": case "February":
       season = "Winter"; break;
    }
}

exercise No. 62

Converting day's names to numbers. Create comment in forum

Q:

Consider the reverse problem to Figure 186, “Converting numbers to day's names ”: We want to map a given day's name to its number as in the following example:

Enter a weekday (Monday to Sunday): Friday
5

Issue an error message in case an inappropriate text is being entered:

Enter a weekday (Monday to Sunday): July
Unknown day name 'July'

Tip

  1. Starting from Java 7 switch statements using strings are allowed.

  2. You may read strings into your application using Scanner.next().

A:

try (final Scanner scan = new Scanner(System.in)) {
    System.out.print("Enter a weekday (Monday to Sunday):>");
    final String day = scan.next();
    switch(day) {
        case "Monday": System.out.println(1); break;
        case "Tuesday": System.out.println(2); break;
        case "Wednesday": System.out.println(3); break;
        case "Thursday": System.out.println(4); break;
        case "Friday": System.out.println(5); break;
        case "Saturday": System.out.println(6); break;
        case "Sunday": System.out.println(7); break;
        default: System.out.println("Unknown day name '" + day + "'");
                 break;
    }
}

exercise No. 63

Day categories. Create comment in forum

Q:

We want to group working days into categories:

Day Category
Monday Start of work week
Tuesday Midweek
Wednesday
Thursday
Friday End of work week
Saturday Weekend
Sunday

Example execution:

Enter a weekday (Monday to Sunday):>Wednesday
Midweek

Tip

Sometimes omitting break statements allowing for fall-through is your friend.

A:

try (final Scanner scan = new Scanner(System.in)) {
    System.out.print("Enter a weekday (Monday to Sunday):>");
    final String day = scan.next();
    switch(day) {
        case "Monday": System.out.println("Start of work week"); break;
        case "Tuesday":
        case "Wednesday":
        case "Thursday": System.out.println("Midweek"); break;
        case "Friday": System.out.println("End of work week"); break;
        case "Saturday":
        case "Sunday": System.out.println("Weekend"); break;
        default: System.out.println("Unknown day name " + day); break;
    }
}

exercise No. 64

Roman numerals, using switch Create comment in forum

Q:

Re-implement Roman numerals using a switch statement rather then an if ... else if ... else.

A:

try (final Scanner scan = new Scanner(System.in)) {

  System.out.print("Enter a number:>");
   final int number = scan.nextInt();

   switch (number) {
      case 1: System.out.println("I"); break;
      case 2: System.out.println("II"); break;
      case 3: System.out.println("III"); break;
      case 4: System.out.println("IV"); break;
      case 5: System.out.println("V"); break;
      case 6: System.out.println("VI"); break;
      case 7: System.out.println("VII"); break;
      case 8: System.out.println("VIII"); break;
      case 9: System.out.println("IX"); break;
      case 10: System.out.println("X"); break;

      default:System.out.println("Decimal value " + number + " not yet implemented");
              break;
   }
}

exercise No. 65

Leap years Create comment in forum

Q:

We want to write an application telling whether a given year is a leap year or not. The following dialogue may serve as an example:

Enter a year:>1980
Year 1980 is a leap year
Enter a year:>1900
Year 1900 is no leap year

You may reuse the user input handling code from the previous examples.

Tip

Read about the leap year algorithm.

A:

A first straightforward rule translation based solution reads:

package start;

import java.util.Scanner;

public class LeapYear {

   public static void main(String[] args) {

      final Scanner scan = new Scanner(System.in); // Read user input
      System.out.print("Enter a year:>");
      final int year = scan.nextInt();
      scan.close();

      if (0 == year % 400) {                    // Every 400 years we do have a leap year.
         System.out.println(
          "Year " + year + " is a leap year");
       } else if (0 == year % 4 &&              // Every 4 years we do have a leap year
                  0 != year % 100) {            // unless year is a multiple of 100.
          System.out.println("Year " + year + " is a leap year");
       } else {
          System.out.println("Year " + year + " is no leap year");
       }
   }
}

This solution contains two identical println("Year " + year + " is a leap year") statements. Developers don't favour redundancies: Rearranging and combining the first and third if branch into one resolves the issue:

public static void main(String[] args) {

  final Scanner scan = new Scanner(System.in); // Read user input
  System.out.print("Enter a year:>");
  final int year = scan.nextInt();
  scan.close();

  if (0 == year % 400 ||              // Every 400 years we do have a leap year.
    (0 == year % 4 &&               // Every 4 years we do have a leap year
     0 != year % 100)) {            // unless year is a multiple of 100.
     System.out.println("Year " + year + " is a leap year");
  } else {
    System.out.println("Year " + year + " is no leap year");
  }
}

Some enthusiasts prefer compact expressions at the expense of readability («Geek syndrome»). The following code is fully equivalent albeit syntactically different:

final Scanner scan = new Scanner(System.in); // Read user input
System.out.print("Enter a year:>");
final int year = scan.nextInt();

System.out.println("Year " + year +
    (year % 400 == 0 || year % 4 == 0 &&  0 != year % 100 ? " is a leap year" : " is no leap year"));

scan.close();