VOOZH about

URL: https://dzone.com/articles/java-switch-duff-device

⇱ Mastering Java Switch Statements Old and New


Related

  1. DZone
  2. Coding
  3. Java
  4. From printTriangularNumber to Duff’s Device: Mastering Java Switch Statements Old and New

From printTriangularNumber to Duff’s Device: Mastering Java Switch Statements Old and New

This post traces that journey using triangular number computation as a practical example of intentional fall-through and connects the technique to Duff's Device.

Likes
Comment
Save
1.2K Views

Join the DZone community and get the full member experience.

Join For Free

In this blog post, we will see how the humble Java switch statement evolved from a fall-through curiosity into a powerful expression, and how understanding its mechanics unlocks classic techniques like Duff's Device.

Java's switch statement has evolved from a fall-through-prone construct into a modern expression syntax introduced in Java 14. The post traces this evolution using a concrete example, a method that computes triangular numbers by intentionally allowing execution to cascade through cases without break statements.

The post also connects this behavior to Duff's Device, a 1983 loop-unrolling technique that uses deliberate fall-through to handle remainder elements before processing full blocks. A comparison of old and new switch syntax outlines trade-offs, and practical guidance is offered on when each form is appropriate.

The Accidental Discovery

I was prepping for the OCP Java 21 exam and stumbled across a tricky question. A method named question2 used a switch statement without any break statements. The output surprised me at first.

Once I traced through it, I renamed the method to printTriangularNumber. That one rename told the whole story. This post dives into why.

The Old Switch Statement

The traditional switch statement has been part of Java since day one. The syntax looks like this:

Java
int day = 3;
switch (day) {
 case 1:
 System.out.println("Monday");
 break;
 case 2:
 System.out.println("Tuesday");
 break;
 case 3:
 System.out.println("Wednesday");
 break;
 default:
 System.out.println("Unknown");
 break;
}


As shown above, every case ends with a break. Without it, execution does not stop. It keeps going into the next case.

The old switch works on int, char, String, and enum types.

Fall-Through: Feature or Bug?

The most misunderstood behavior in switch is fall-through. When you omit break, execution literally falls into the next case.

Java
int x = 2;
switch (x) {
 case 3: System.out.println("three");
 case 2: System.out.println("two"); // jumps here
 case 1: System.out.println("one"); // falls through
 default: System.out.println("done"); // falls through
}


Output:

Plain Text
two
one
done


Most developers treat this as a bug waiting to happen. They are not wrong. Forgetting a break is one of the most common Java mistakes. But intentional fall-through is a different story. It is a deliberate tool. And printTriangularNumber is the perfect example.

printTriangularNumber: Fall-Through in Action

Here is the method I renamed from question2 during my OCP prep:

Java
private static void printTriangularNumber(int n) {
 int res = 0;
 switch (n) {
 case 5:
 res += 5;
 case 4:
 res += 4;
 case 3:
 res += 3;
 case 2:
 res += 2;
 case 1:
 res += 1;
 default:
 break;
 }

    System.out.println(res == 0 ? "Ok, bye." : res);


Let us trace through n = 4:

  1. Jumps to case 4, adds 4. res = 4
  2. Falls to case 3, adds 3. res = 7
  3. Falls to case 2, adds 2. res = 9
  4. Falls to case 1, adds 1. res = 10
  5. Hits default, breaks

Output: 10

The pattern for each input:

n Result Formula
1 1 1
2 3 2+1
3 6 3+2+1
4 10 4+3+2+1
5 15 5+4+3+2+1


This is n * (n + 1) / 2, the triangular number formula. The fall-through is doing the summation for you. Each case accumulates the remaining values by simply not stopping.

For n = 0 or any value above 5, no case matches, default fires immediately, and res stays 0. The ternary prints "Ok, bye.".

I personally find it a beautiful example of using language semantics intentionally. This is also the kind of question the OCP exam loves to throw at you.

The New Switch Expression (Java 14+)

Java 14 introduced switch expressions as a standard feature. The arrow syntax -> eliminates fall-through entirely. Each arm is independent.

Java
int day = 3;
String name = switch (day) {
 case 1 -> "Monday";
 case 2 -> "Tuesday";
 case 3 -> "Wednesday";
 default -> "Unknown";
};
System.out.println(name); // Wednesday


A few things to notice here:

  • Switch is now an expression. It returns a value.
  • The arrow -> replaces : and break together.
  • No fall-through. Each arm executes independently.
  • Multiple labels on a single arm: case 1, 7 -> "Weekend";

You can also use it inline:

Java
System.out.println(switch (day) {
 case 1, 7 -> "Weekend";
 default -> "Weekday";
});


Much cleaner. Much safer.

Switch Expressions With Yield

Sometimes you need more than a single expression in an arm. That is where yield comes in.

Java
int n = 4;
int result = switch (n) {
 case 1, 2 -> n * 10;
 case 3, 4 -> {
 int temp = n * n;
 System.out.println("Computing for: " + n);
 yield temp; // return value from block
 }
 default -> 0;
};
System.out.println(result); // 16


Think of yield as the return statement for a switch block arm. You need it whenever the arm has multiple statements inside {}.

A common mistake is using return instead of yield inside a switch expression block. That compiles only inside a method and it returns from the entire method, not just the switch. Always use yield inside switch expression blocks.

Duff's Device: Fall-Through Taken to the Extreme

Now that we understand fall-through well, let us look at the most famous intentional use of it: Duff's Device.

Tom Duff invented this in 1983 to speed up memory copy operations by reducing loop branch overhead. The trick is to unroll the copy loop and use a switch to jump into the middle of it based on the remainder.

In Java, we replicate it in two clean phases since Java does not allow interleaved switch+loop syntax:

Java
public static void duffCopy(int[] src, int[] dst, int n) {
 int i = 0;
 int rem = n % 4;

 // Phase 1: handle remainder via fall-through
 switch (rem) {
 case 3: dst[i] = src[i]; i++;
 case 2: dst[i] = src[i]; i++;
 case 1: dst[i] = src[i]; i++;
 case 0: break;
 }

 // Phase 2: full blocks of 4
 int fullBlocks = (n - rem) / 4;
 while (fullBlocks-- > 0) {
 dst[i] = src[i]; i++;
 dst[i] = src[i]; i++;
 dst[i] = src[i]; i++;
 dst[i] = src[i]; i++;
 }
}


Let us trace through n = 13:

  1. rem = 13 % 4 = 1
  2. Switch jumps to case 1, copies 1 element. i = 1
  3. fullBlocks = (13 - 1) / 4 = 3
  4. Loop runs 3 times, copying 4 elements each time
  5. Total: 1 + 12 = 13 elements

The Python equivalent makes the two phases explicit:

Python
def duff_copy(src, n):
 dst = [None] * n
 rem = n % 4

 for i in range(rem): # Phase 1: remainder
 dst[i] = src[i]

 i = rem
 while i < n: # Phase 2: full blocks
 dst[i] = src[i]
 dst[i+1] = src[i+1]
 dst[i+2] = src[i+2]
 dst[i+3] = src[i+3]
 i += 4

    return dst


The connection to printTriangularNumber is direct. Both use fall-through intentionally. In printTriangularNumber, the switch jumps to the right case and accumulates downward. In Duff's Device, the switch jumps to the right case and copies the remainder before the main loop takes over.

Old vs. New Switch at a Glance

Feature Old Switch (:) New Switch (->)
Fall-through Yes (default) No
Returns value No Yes
break needed Yes No
Multiple labels No Yes (case 1, 2 ->)
Block with yield No Yes
Null safe No Yes (Java 21 preview)
OCP exam topic Yes Yes


Which One Should You Use?

For new code, always prefer the switch expression with ->. It is safer, cleaner, and expressive. Your reviewers will thank you.

Reserve the old switch with fall-through only when you genuinely need the cascading behavior, like in printTriangularNumber or a hand-tuned loop like Duff's Device. In those cases, add a comment explaining the intent. Otherwise, the next developer (including future you) will assume the break is missing by accident.

My personal observation: the OCP Java 21 exam tests both heavily. Knowing when fall-through is intentional versus accidental is the key distinction examiners probe. Make sure you can trace through any switch block without running it.

Happy testing!

What is your take: is intentional fall-through clever engineering or a maintenance nightmare waiting to happen? Drop your thoughts below!

Java (programming language) Data Types

Published at DZone with permission of NaveenKumar Namachivayam. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Top Java Security Vulnerabilities and How to Prevent Them in Modern Java
  • Multithreading in Modern Java: Advanced Benefits and Best Practices
  • Apache Spark 3 to Apache Spark 4 Migration: What Breaks, What Improves, What's Mandatory
  • Memory Optimization and Utilization in Java 25 LTS: Practical Best Practices

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

Let's be friends: