<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk" -->

---
title: Preparing for Change: Safe Switching over Sealed APIs
description: Exhaustive switch expressions over sealed types cover only the permitted subtypes known at compile time, and adding a new permitted subtype later can break...
canonical: https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Preparing for Change: Safe Switching over Sealed APIs | daily.dev
og:description: Exhaustive switch expressions over sealed types cover only the permitted subtypes known at compile time, and adding a new permitted subtype later can break...
og:url: https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk
og:image: https://api.daily.dev/og/posts/uNRzsaIFk.png
og:image:alt: Preparing for Change: Safe Switching over Sealed APIs
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Preparing for Change: Safe Switching over Sealed APIs

**[Inside Java](https://daily.dev/sources/inside_java)** · 10 min read · 1 upvotes · 0 comments

## Summary

Exhaustive switch expressions over sealed types cover only the permitted subtypes known at compile time, and adding a new permitted subtype later can break existing switches — causing compile errors on recompilation or a MatchException at runtime. Guidance covers why default should almost always be avoided in these switches (it hides broken assumptions and doesn't catch null), how sealed type authors should document expected evolution, and detailed rules for using match-all cases when covering every subtype individually is impractical, including handling concrete sealed classes and multi-branch hierarchies.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://inside.java/2026/08/14/java-exhaustiveness-guide>

## Questions this post answers

### Should I use a default case when switching over a sealed interface in Java?

No, using default is almost never the right choice for a switch over a sealed type. It hides the developer's intent that the switch is exhaustive, preventing the compiler from flagging the switch when a new permitted subtype is added later, and it can suppress useful runtime detection of unexpected values. It also doesn't handle a null selector, so a separate null check or case null is still required.

_Developers designing sealed hierarchies weigh tradeoffs like this one on daily.dev before locking in an API contract._

### What happens if I add a new permitted subtype to a sealed interface after existing switch statements were written?

Existing exhaustive switch expressions over that sealed type may stop compiling once recompiled, because the new subtype isn't covered by any case, and if the switch isn't recompiled it can throw MatchException at runtime when the new subtype value is encountered. This is intentional: it surfaces broken assumptions in code written before the sealed type evolved.

_Teams evolving shared sealed APIs track this kind of breaking-change ripple effect through daily.dev._

### How do I write an exhaustive switch when a sealed type has too many permitted subtypes to list individually?

Use the narrowest possible type pattern that still covers the remaining cases, called a match-all case, such as case A other rather than a broader case Object other or case AB other. For multi-branch sealed hierarchies, totalize each branch separately (for example case A other and case B other) rather than one broad case for the whole hierarchy, since this preserves exhaustiveness checking on the branches that are fully enumerated.

_Java developers refining pattern-matching switch designs compare approaches like this via daily.dev._

## Similar posts on daily.dev

- [Java sealed classes and exhaustive pattern matching](https://daily.dev/posts/java-sealed-classes-and-exhaustive-pattern-matching-pahwvvg9e) · Neil Madden · 19 upvotes · 0 comments
- [Sealed Classes in Dart: Safe, Complete switch by Design](https://daily.dev/posts/sealed-classes-in-dart-safe-complete-switch-by-design-oqklngg2m) · Medium · 0 upvotes · 0 comments
- [Closed Hierarchies in C\# 15: Exhaustive Switches and Versioning — Daily DevOps & .NET](https://daily.dev/posts/closed-hierarchies-in-c-15-exhaustive-switches-and-versioning-daily-devops-net-vaomj42s2) · Daily DevOps & .NET · 24 upvotes · 2 comments
- [JEP 530: Primitive Types in Patterns, instanceof, and switch \(Fourth Preview\)](https://daily.dev/posts/jep-530-primitive-types-in-patterns-instanceof-and-switch-fourth-preview--vfd5lcvmr) · Inside Java · 0 upvotes · 0 comments

---

Tags: [#java](https://daily.dev/tags/java), [#architecture](https://daily.dev/tags/architecture)

[View this post on daily.dev](https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Preparing for Change: Safe Switching over Sealed APIs","url":"https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk"},"datePublished":"2026-08-14T06:10:47.166Z","dateModified":"2026-09-14T06:17:15.032Z","description":"Exhaustive switch expressions over sealed types cover only the permitted subtypes known at compile time, and adding a new permitted subtype later can break...","image":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","thumbnailUrl":"https://media.daily.dev/image/upload/s--58gMhC4P--/f_auto/v1722860399/public/Placeholder%2012","isAccessibleForFree":true,"articleSection":"Inside Java","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Inside Java","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/de5992d95f374790bdfd2ae03a16f6e3","url":"https://daily.dev/sources/inside_java"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"java,architecture","timeRequired":"PT10M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Inside Java","item":"https://daily.dev/sources/inside_java"},{"@type":"ListItem","position":3,"name":"Preparing for Change: Safe Switching over Sealed APIs"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/preparing-for-change-safe-switching-over-sealed-apis-unrzsaifk#faq","mainEntity":[{"@type":"Question","name":"Should I use a default case when switching over a sealed interface in Java?","acceptedAnswer":{"@type":"Answer","text":"No, using default is almost never the right choice for a switch over a sealed type. It hides the developer's intent that the switch is exhaustive, preventing the compiler from flagging the switch when a new permitted subtype is added later, and it can suppress useful runtime detection of unexpected values. It also doesn't handle a null selector, so a separate null check or case null is still required. Developers designing sealed hierarchies weigh tradeoffs like this one on daily.dev before locking in an API contract."}},{"@type":"Question","name":"What happens if I add a new permitted subtype to a sealed interface after existing switch statements were written?","acceptedAnswer":{"@type":"Answer","text":"Existing exhaustive switch expressions over that sealed type may stop compiling once recompiled, because the new subtype isn't covered by any case, and if the switch isn't recompiled it can throw MatchException at runtime when the new subtype value is encountered. This is intentional: it surfaces broken assumptions in code written before the sealed type evolved. Teams evolving shared sealed APIs track this kind of breaking-change ripple effect through daily.dev."}},{"@type":"Question","name":"How do I write an exhaustive switch when a sealed type has too many permitted subtypes to list individually?","acceptedAnswer":{"@type":"Answer","text":"Use the narrowest possible type pattern that still covers the remaining cases, called a match-all case, such as case A other rather than a broader case Object other or case AB other. For multi-branch sealed hierarchies, totalize each branch separately (for example case A other and case B other) rather than one broad case for the whole hierarchy, since this preserves exhaustiveness checking on the branches that are fully enumerated. Java developers refining pattern-matching switch designs compare approaches like this via daily.dev."}}]}
```

