Switch in Java

Switch statement in Java

I discovered lately some things in java that I did not know yet. The switch statement in the java language switch in java has some weird things. First let’s create an example user story. I will write code afterwards.

I want to buy shoes. I go shopping and can choose from a lot of colors. But I do not want any shoe. I will buy a shoe only if the following is true:

  • If it is a shoe to walk I want the color brown
  • If it is a shoe to dance with, I want a pair black ones.
  • The color blue is for running shoes
  • Other shoes should be yellow

I could implement such code in a method with only if statements. Then the code will look like this:

public void chooseTheColor(String typeShoes){
    if ( typeShoes == "walk" ) {
        System.out.println( "brown" );
    } else if ( typeShoes == "dance" ) {
        System.out.println( "black" );
    } else if ( typeShoes == "running" ) {
        System.out.println( "blue" );
    } else {
        System.out.println( "yellow" );
    }
}

chooseTheColor("dance"); // will print black

This is a way to write our demands. There is however an other way to program the same logic. Using a switch command.

public void chooseTheColor(String typeShoes){
    switch ( typeShoes ) {
        case "walk":
            System.out.println( "brown" );
            break;
        case "dance":
            System.out.println( "black" );
            break;
        case "running":
            System.out.println( "blue" );
            break;
        default:
            System.out.println( "yellow" );
    }
}

chooseTheColor("dance"); // will print black

This function has the same output, but is better to read. What I discovered is that the default keyword does not have to be the latest one. This means that the following code will output the same result.

public void chooseTheColor(String typeShoes){
    switch ( typeShoes ) {
        case "walk":
            System.out.println( "brown" );
            break;
        default:
            System.out.println( "yellow" );
            break;
        case "dance":
            System.out.println( "black" );
            break;
        case "running":
            System.out.println( "blue" );
            break;
    }
}

chooseTheColor("dance"); // will print black

At first I thought that because the default keyword was before the dance option it would execute the default block. But it is not the case. Java does this like it supposed to be.

Switch Variables

The difficult part in a switch statement is the data types of Java. The type of the variable behind the switch must be the same type of the things that are behind the case keyword. It is also valid that the value can be casted the type of the variable.

Not all data types can be in a switch statement. Only the following are valid:

  • Integer and int
  • Byte and byte
  • Short and short
  • Character and char
  • String
  • enum values
  • var type if it can be casted to one of the previous types.

Case Values

You can not place whatever you want after the case keyword. There are some conditions:

  • The values must be constants at compile time
  • The values must be of the same type as the switch variable
  • The values must be final or literals or enum constants

This means that the following is not correct java code:

Incompatible Types 

public void chooseTheColor(String typeShoes){
    switch ( typeShoes ) {
        case "walk":
            System.out.println( "brown" );
            break;
        case 3:
            System.out.println( "black" );
            break;
        case "running":
            System.out.println( "blue" );
            break;
        default:
            System.out.println( "yellow" );
            break;
    }
}

chooseTheColor("dance"); // will print black

The compilation of this code will result in an error:

error: incompatible types: int cannot be converted to String 
    case 3:
         ^

No constant in case values

public void chooseTheColor(int typeShoes){
    int walk = 1;
    switch ( typeShoes ) {
        case walk:
            System.out.println( "brown" );
            break;
        case 2:
            System.out.println( "black" );
            break;
        case 3:
            System.out.println( "blue" );
            break;
        default:
            System.out.println( "yellow" );
            break;
    }
}

chooseTheColor(1); // will print black

The previous example will give a compilation error too.

error: constant expression required
    case walk:
         ^

The error is here because the walk variable is not a final variable. If the walk variable is final, the code will compile.

final int walk = 1;

Is final enough ?

No it is not. Check the following code: 

public int getWalkNumber() {
    return 1;
}

public void chooseTheColor(int typeShoes){
    final int walk = getWalkNumber();
    switch ( typeShoes ) {
        case walk:
            System.out.println( "brown" );
            break;
        case 2:
            System.out.println( "black" );
            break;
        case 3:
            System.out.println( "blue" );
            break;
        default:
            System.out.println( "yellow" );
            break;
    }
}

chooseTheColor(1); // will print black

And again we get a compilation error:

error: non-static method getWalkNumber() cannot be referenced from a static context
final int walk = getWalkNumber(); 
          ^ 
error: constant expression required
case walk:
     ^ 

A method is not a good idea to initialize a final variable in this context. The value should be known at compile time. Methods will be evaluated at runtime. That is why this results in a compilation error.

You see, a simple switch statement in java has some weird things in it. Specially the types that are mandatory in java.

About the author

I currently work as a Test Automation Consultant at b.ignited. Here I work for different clients in different industries to help them start and speed up their testing cycles

I’ve been testing software since 2000 when I became involved in testing telephone applications and hardware. Since then, I’ve been able to expand my experience by testing a variety of embedded, web, mobile and desktop applications. I have used various development methodologies from waterfall to agile.

I consider myself to be a lifelong learner.