18

I have this code with the switch statement which I got from this post, and it works absolutely fine:

String getOrdinal(final int day) {
    if (day >= 11 && day <= 13) {
        return "th";
    }
    switch (day % 10) {
        case 1: return "st";
        case 2: return "nd";
        case 3: return "rd";
        default: return "th";
    }
}

But if I change it to something like the following, it breaks, as all the cases besides case 1 gets executed:

  static String getOrdinal(final int day) {
    StringBuilder ordinalBuilder = new StringBuilder();
    ordinalBuilder.append("<sup>");
    if (day >= 11 && day <= 13) {
        ordinalBuilder.append("th") ;
    }
    switch (day % 10) {
        case 1: ordinalBuilder.append("st");
        case 2: ordinalBuilder.append("nd");
        case 3: ordinalBuilder.append("rd");
        default: ordinalBuilder.append("th");
    }
    ordinalBuilder.append("</sup>");
   return ordinalBuilder.toString();
 }

This prints 2<sup>ndrdth</sup> when I pass in 2. I tried changing the builder to buffer but I got the same response... Could this be a bug or am I making some mistake?

0xCursor
  • 2,242
  • 4
  • 15
  • 33
Hell Boy
  • 899
  • 5
  • 12
  • 22
  • 4
    Nothing is gained by inlining the switch statement, you should have just kept the `getOrdinal` method separate and had your code call it. Try passing 11, 12, or 13 to your code. There is another bug you created. – Tim Bender Nov 09 '11 at 00:44
  • 1
    I wish I could give more +1s to @TimBender. This question is the very definition of cargo cult programming. – CanSpice Nov 09 '11 at 00:56

8 Answers8

58

It's a bug in your code. You forgot to put in a break after each case:

switch (day % 10) {
    case 1: ordinalBuilder.append("st"); break;
    case 2: ordinalBuilder.append("nd"); break;
    case 3: ordinalBuilder.append("rd"); break;
    default: ordinalBuilder.append("th"); break;
}
Naman
  • 27,789
  • 26
  • 218
  • 353
CanSpice
  • 34,814
  • 10
  • 72
  • 86
28

I don't see any bug here, at least not in the way the language is working. The behavior of a switch statement, by design, is that it will start executing statements at the case label which matches the argument, and then continue until the end of the block. So

switch (x) {
    case 1:
        // do thing 1
    case 2:
        // do thing 2
    case 3:
        // do thing 3
    default:
        // do nothing
}

will do both things 2 and 3 if x is 2, and will do things 1, 2, and 3 if x is 1.

To get the behavior you're probably looking for, end each case with a break:

switch (x) {
    case 1:
        // do thing 1
        break;
    case 2:
        // do thing 2
        break;
    case 3:
        // do thing 3
        break;
    default:
        // do nothing
        break;
}

(strictly speaking the break at the very end is unnecessary, but I often put it in out of habit).

The reason you didn't have this problem in the first code example is that return is like a super-break: it has the same effect as break, namely ending execution within the switch block, but it also ends execution of the whole method.

David Z
  • 128,184
  • 27
  • 255
  • 279
9

you need to add a 'break' statement in every switch case. It was worked previously because you made a return from method...

javagirl
  • 1,635
  • 6
  • 27
  • 43
6

A "break;" statement separates the cases from one another so in order to execute the statements in a specific case just break the case as soon as it comes to an end.

If you don't use break the compiler thinks that it can continue execution of all the cases up to the end of the program.

poupou
  • 43,413
  • 6
  • 77
  • 174
Bhargava
  • 61
  • 1
3

The first version returns before continuing on in the case statement. The second version needs a break; statement to get the same behavior.

Scott A
  • 7,745
  • 3
  • 33
  • 46
1

Luckily with the introduction of switch statements on Java 12 which also introduced

"arrow case" labels that eliminate the need for break statements to prevent fall through (source).

Therefore the modern version of your code looks like the following:

String getOrdinal(final int day) {
    if (day >= 11 && day <= 13) {
        return "th";
    }
    return switch (day % 10) {
        case 1 -> "st";
        case 2 -> "nd";
        case 3 ->  "rd";
        default ->  "th";
    };
}
dreamcrash
  • 47,137
  • 25
  • 94
  • 117
0

I see this question is over 8 years old, but this answer should help anyone landing on this page.

Firstly lets's understand how switch cases work. In C, C++, Java, JavaScript, and PHP while executing switch statements all the cases following the satisfactory case are executed, unlike in Go where only selected case is executed. For example:

public class Main
{
    public static void main(String[] args) {
        int day = 11;
        switch (day % 10) {
            case 1: System.out.println("st"); 
            case 2: System.out.println("nd");
            case 3: System.out.println("rd");
            default: System.out.println("th");
        }
    }
}

Currently, day value is set to 11 and hence very first case satisfy the condition, and hence all below cases would be executed. The output should look like the one below:

st                                                                                                                                                                           
nd                                                                                                                                                                           
rd                                                                                                                                                                           
th 

Now let's change day value to 13 resulting in the third case to satisfy the condition and hence below output is obtained:

rd
th

Hence if you want to break the code after first satisfactory case is found then put break; condition in the end. In the code mentioned in the question return; does the job of breaking the code.

Also, most of the novice java programmers believe that SWITCH statements are syntactical sugar to IF statements wherein programmers don't have to repetitively mention conditions. But that's not the case as IF's are meant to exit after the execution of satisfactory condition while SWITCH still continues execution.

Switch cases can be utilized to achieve the purpose like one mentioned in below example:
wherein
for Grade A "Excellent!" should be printed
for Grade B and C "Well done" should be printed
for Grade D "You passed \n Try hard next time" should be printed
for Grade F "Try hard next time" should be printed
and if not a valid case i.e grade is found than "Invalid Grade" should be printed.

public class Test {

   public static void main(String args[]) {
      // char grade = args[0].charAt(0);
      char grade = 'C';

      switch(grade) {
         case 'A' :
            System.out.println("Excellent!");
            break;
         case 'B' :
         case 'C' :
            System.out.println("Well done");
            break;
         case 'D' :
            System.out.println("You passed");
         case 'F' :
            System.out.println("Try hard next time");
            break;
         default :
            System.out.println("Invalid grade");
      }
      System.out.println("Your grade is " + grade);
   }
}
Darshan Dedhia
  • 113
  • 1
  • 1
  • 5
0

Add a break statement at the end of the every line in each case or just use the return statement.

hp77
  • 75
  • 1
  • 2
  • 10