Switch

2 minute read

Expressions are nice

Statements vs. Expressions

In Java, expressions and statements are distinct.

  • Expressions return values, and
  • Statements perform actions

  • An expression can be variables, operators, and function calls that can be evaluated to produce a single value.
    • Example: x + y, Math.sqrt(16), str.length(), 3 * (a + b)
  • A statement Statements perform action but do not return anything
    • Statement cause side-effects (except one statement no-op)
    • Statements are used to control the flow of a program, define variables, execute loops, conditionals, and function declarations, and manage side effects.
  • Example : if, for, while, switch, return, and variable declarations like int x = 5;

In JavaScript, expressions can be used as statements, and statements can often be used as expressions.

  • For example, console.log(x + y);, where the expression x + y is used as a statement.

Switch Statement (Traditional):

  • Switch as a statement NEEDS BREAK
  • verbose
  • error prone , causes side-effects and
  • force mutability
int grade = 8;
String gradeValue;

switch (grade) {
    case 9:
    case 10:
        gradeValue = "A";
        break;
    case 8:
        gradeValue = "B";
        break;
    case 7:
        gradeValue = "C";
        break;
    case 6:
        gradeValue = "D";
        break;
    default:
        gradeValue = "F";
}

System.out.println("Grade: " + gradeValue);

Switch Expression with Yield (Java 13 onwards):

No need to write break in this case

  • concise
  • less error prone
  • no side effect
int score = Math.min(score/10, 10);
String grade = switch (score) {
    case 9,10 -> "A";
    case 8 -> "B";
    case 7 -> "C";
    case 6 -> "D";
    default -> "F";
};

Switch taking an Enum

enum When{DAY, NIGHT}//, DAWN}

public static String lights(When when){//When is an Enum
    return switch (when){
        case DAY -> "No Light";
        case NIGHT -> "Lights needed";
    };
}

If you don’t write the default, they write it for you.

the compiler fails if a new element gets added and recompiled, which is good

default -> never happens so how to cover the test case for it?

Should NOT write Default.

public static String process(Object obj){
  return switch (obj){
    case String s -> "It's a string: " + s;
    case Integer i when i > 5 -> "> than 5 " + i;//Guarded pattern
    case Integer i -> "Integer integer: " + i;//LAbel Dominance if swapped with previous line : Label is dominated by a preceding case label 'Integer i'
    case null -> "It's null";
    case Double d -> "It's a double: ";//Primitive type matching
    case Long l -> "It's a long: ";//Primitive type matching
    default -> "Unknown type: " + obj.getClass().getName();
  };
}

Sealed Classes & Record Classes Pattern Matching interplay with Switch Expressions

sealed interface Shape permits Circle, Rectangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double length, double width) implements Shape {} 
public static double area(Shape shape) {
    return switch (shape) {
        case Circle c -> Math.PI * c.radius() * c.radius();
        case Rectangle r -> r.length() * r.width();
    };
}

Tags:

Categories:

Updated: