Issues with traditional switch constructs

At present, the syntax of switch statements is highly constrained. It is not as powerful as the if-else construct. With if-else constructs, you can define and match complex patterns; but not with the switch construct. Also, the syntax of switch is verbose, which makes it visually annoying. This can lead to error-prone code that can be difficult to debug.

Let's work with an example to show all of these issues. The following example defines an enum, Size. The Shirt class defines a setSize() method, which accepts Size and accordingly assigns an integer value to the instance variable, length:

enum Size {XS, S, M, L, XL, XXL};          
class Shirt { 
    private int length; 
    public void setSize(Size size) { 
        switch(size) { 
            case XS :   length = 10; 
                        System.out.println(length); 
                        break; 
            case S  :   length = 12; 
                        System.out.println(length); 
                        break; 
            case M  :   length = 14; 
                        System.out.println(length); 
            case L  :   length = 16; 
                        break; 
            case XL :   length = 18; 
                        System.out.println(length); 
                        break; 
            case XXL:   length = 20; 
                        System.out.println(length); 
                        break; 
        } 
    } 
} 

Here's how you can call the preceding method:

Shirt s = new Shirt(); 
s.setSize(Size.XXL); 
System.out.println(s.length);

The preceding code outputs the following expected results:

20 
20 

However, let's see what happens when you try executing the following code:

Shirt s = new Shirt(); 
s.setSize(Size.M); 
System.out.println(s.length); 

The preceding code outputs an unexpected mismatch in the values:

14 
16 

What do you think is the reason for these mismatching values? To answer this question, here's a quick recap—the switch branches (that is, the case labels) in existing switch constructs must include a break statement to prevent the fall through of the control. This essentially means that, when the control finds a matching case value, it will execute the statements until it finds a break statement or it reaches the end of the switch construct.

On closer inspection, you'll realize that the branch corresponding to the M value doesn't define a break statement. The branch corresponding to the next case, that is, L, misses the System.out.println value statement. So, when you call s.setSize(Size.M), the following happens:

  1. 14 is assigned to the length instance variable
  2. System.out.println() outputs 14
  3. Control falls through the arm corresponding to the L value
  4. 16 is assigned to the length instance variable
The traditional switch construct has a default fall through of control across the case labels, in the absence of a break statement; this leads to unexpected bugs.

The switch construct works as a block. However, if you revisit the example code in the preceding section, you'll agree that the language construct takes the focus away from the business logic and introduces complexity.

This is shown in the following diagram:

The new switch expressions are here to bring the spotlight back to the business logic.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.156.251