Skip Top Navigation Bar

Switch Expressions - Determine a Value


Before we look at Switch Expressions, let's take a few moments to explore Switch Statements and the difference between them and Switch Expressions.

If you are an AP CSA teacher, please remember that switch statements and switch expressions are OUTSIDE the AP CSA Java subset. Therefore, this topic does not need to be taught to students and might be best left for after the AP exam or a post-AP type course.

What are switch statements used for?

  • Switch statements are often used when you have a menu of options to choose from.
  • Algorithms that use switch statements can also be written with a series of nested if..else statements.
  • Using switch statements instead of a series of nested if..else statements can make code more readable.
  • Default statements are often required to ensure that all cases are addressed, and the switch is exhaustive.
  • Only certain data types can be used in a switch: byte, short, char, int, long, enums, String, Integer, Short, Byte, and Long

Basic Structure of a Switch Statement

switch (<variable>) { 
   case <value>: {
      //statements to use if variable == value
      break; 
   }
   //additional case statements
   default: {
      //statements to use if no case values match the value of variable
      break;
   }
} 

Grade Level Example

Consider the following code segment which prints out what year a student is in high school based on the grade given. A grade of 9 prints "Freshman"; a grade of 10 prints "Sophomore"; a grade of 11 prints "Junior"; a grade of 12 prints "Senior"; and all other values of grade prints "Not in High School“.

We can re-write this if statement as a switch statement as follows:

Often a switch statement can make the code more readable, especially as the options available grow.

Basic Structure of a Switch Statement with Lambda

We can use lambda notation when writing switch statements as well.

switch (<variable>) { 
   case <value> -> //statements to use if variable == value
   //additional case statements
   default -> //statements to use if no case values match the value of variable
}

We can re-write the switch statement above with lambda as follows:

Switch Expressions

How are switch expressions different from switch statements?

  • Switch expressions yield a value, typically assigned to a variable.
  • Switch expressions use the keyword yield and do not require a break statement as yield will return a value and the execution stops.
  • Switch expressions require a ; at the end.

Basic Structure of a Switch Expression

<type> returnVariable = switch (<variable>) { 
   case <value>: {
      yield valueAssignedtoreturnVariable; 
   }
   //additional case statements
   default: {
      yield valueAssignedtoreturnVariable; 
   }
};

Revisiting the Grade Level Example

We've embedded the expression into a statement requiring a semi-colon at the end.

Note that the keyword yield is being used to return the value for each case.

Basic Structure of a Switch Expression with Lambda

<type> returnVariable = switch (<variable>) { 
   case <value> -> //value to assign if variable == value ;
   //additional case statements
   default -> //value to assign if no case values match the value of variable ;
}; 

The above example re-written with lambda:

What's Next for Switch Statements and Switch Expressions?

Previewing in JDK 24, Primitive Types in Patterns, instanceof, and switch.

NOTE: Preview features are not guaranteed to be released. Potential new features are proposed openly in the community via a document called a JDK Enhancement Proposal or JEP.

Each JEP goes through the following lifecycle:

  • Each must be approved for inclusion with a target release.
  • Each goes through at least 1 preview cycle to address feedback. Most go through 2-3 previews but it could be more.
  • Once feedback is addressed and the community approves the implementation, the JEP is targeted for a release as a final candidate.
  • With each release revision, the proposal documentation is updated to reflect the current state of the proposal and it is given a new identifying number to ensure traceability through history on versions of the idea.

JEP 488: Primitive Types in Patterns, instanceof, and switch

For instanceof – allows the use of instanceof with primitive types instead of just reference types. It checks whether a variable can be represented by a specific type without any loss of precision of data.

For switch - allows for the use of a switch over all primitive types.

To ensure all cases are being covered, we can add guards to our switch expressions.

int x = -1; //change the value of x for other outputs
String result = switch (x){
    case 0 -> "zero";
    case int y when y < 0 -> "negative";
    case int z -> "positive";
}
System.out.println (result);
  • when is being used as a condition
  • The third case is for anything that isn’t the first two
  • No default is required, the third case acts as the default

Other Primitive Data Types for Switch

Currently, we can not use a switch for boolean variables. This new feature would allow for the following:

int x = 12; //change the value of x for other outputs
String result = switch(x % 2 == 0) {
   case true -> "Even";
   case false -> "Odd";
}
System.out.println (result);

Or if you wanted to report out the information, use a switch statement:

int x = 11; //change the value of x for other outputs
switch(x % 2 == 0) {
    case true -> System.out.println ("Even");
    case false -> System.out.println ("Odd");
}

Switch Expressions and the AP CSA Free Response Exam

If you are an AP CSA teacher, please remember that switch statements and switch expressions are OUTSIDE the AP CSA Java subset. Therefore, this topic does not need to be taught to students and might be best left for after the AP exam or a post-AP type course.

Example 1: 2024 Free Response Question 1

In 2024, question 1 can be re-written using the ternary conditional operator. The full question and solution can be found here.

To summarize, this question has a class called Feeder that has an instance variable currentFood and two methods simulateOneDay and simulateManyDays. Students are asked to implement these two methods. We are looking at writing the simulateOneDay method.

To simulate a day at the bird feeder, students will need to do the following:

  • generate a random number to determine if a bear visited the bird feeder.
  • If a bear came to the feeder, the value of currentFood would be set to 0.
  • If there is no bear, then another number is simulate the amount of food each bird will consume.
  • If the amount of food the birds consumed exceeds the amount in the feeder, the value of currentFood is 0, otherwise the amount consumed is subtracted from currentFood.

An example solution is as follows:

In the previous example, I used a boolean variable bearPresent and a nested if statement. Unfortunately with JDK 23, we cannot use a switch statement or expression with boolean, so we are using an int variable bearPresent instead.

I needed to use a default to cover all cases where bearPresent wasn't 0 or 1, which is impossible the way that I wrote it, but the default is necessary anyway.

I could also have used lambda notation as follows:

Preview features Primitive Types in Patterns, instanceof, and switch and AP CSA FRQ

Previewing in JDK 24, Primitive Types in Patterns, instanceof, and switch.

  • For switch - allows for the use of a switch over all primitive types.

To ensure all cases are being covered, we can add guards to our switch expressions.

So, if this preview feature becomes incorporated into the Java language allowing us to use boolean variables in switch statements and expressions, I could write the following:

public void simulateOneDay (int numBirds) {
    boolean bearPresent = false;
    double bear = Math.random() * 100;
    if (bear <= 5) {
        bearPresent = !bearPresent;
    }
    int birdConsumed = ((int) (Math.random() * 41) + 10) * numBirds;
    currentFood = switch (bearPresent) {
        case true:
            yield 0;
        case false:
            yield ((birdConsumed >= currentFood) ? 0 : currentFood - birdConsumed);
    };
}

Or if I'm using lambda notation:

public void simulateOneDay (int numBirds) {
    boolean bearPresent = false;
    double bear = Math.random() * 100;
    if (bear <= 5) {
        bearPresent = !bearPresent;
    }
    int birdConsumed = ((int) (Math.random() * 41) + 10) * numBirds;
    currentFood = switch (bearPresent) {
        case true -> 0;
        case false -> ((birdConsumed >= currentFood) ? 0 : currentFood - birdConsumed);
    };
}

AP CSA Scoring and Teaching

  • Student solutions that use correct Java syntax can earn full credit for their solution
  • Questions are written with an in AP Java subset solution in mind
  • Students should be encouraged to write solutions within the AP Java Subset

Resources

Calculator - Using Conditionals and Lambda Mini-Lab