Java 17 introdujo las clases y interfaces selladas, una característica diseñada para proporcionar una forma más declarativa de restringir las jerarquías de herencia. A diferencia de la palabra clave `final`, que impide todas las subclases, o el acceso de paquete privado, que limita las subclases al mismo paquete, el modificador `sealed` permite a un desarrollador enumerar explícitamente los subtipos permitidos. Por ejemplo, una interfaz `sealed` puede especificar exactamente qué clases están permitidas para implementarla mediante una cláusula `permits`. Esto es particularmente útil para modelar 'tipos' de valores, como diferentes formas en una biblioteca de gráficos, donde el autor desea asegurar que solo un conjunto específico y conocido de tipos pueda ser utilizado en el sistema.

Uno de los principales beneficios técnicos de este diseño es su integración con las expresiones switch para proporcionar un emparejamiento de patrones exhaustivo. Cuando una expresión switch opera sobre un tipo sellado, el compilador de Java puede determinar el conjunto completo de subtipos posibles. Si un desarrollador cubre cada subtipo permitido, el compilador permite la omisión de una cláusula `default`. Si falta un subtipo, el compilador genera un error en tiempo de compilación. Esto proporciona un nivel de seguridad superior al de las sentencias switch estándar, donde un caso faltante podría descubrirse solo como un error en tiempo de ejecución. Este mecanismo refleja los tipos de datos algebraicos que se encuentran en lenguajes de programación funcional como Haskell o ML, donde la estructura de los datos está estrictamente definida.

Sin embargo, la aplicación práctica de las clases selladas implica una compensación significativa con respecto a la estabilidad de la API y la compilación separada. Si bien el compilador impone la exhaustividad durante una compilación completa, no puede hacerlo si el código de un consumidor no se recompila cuando se añade un nuevo subtipo a una jerarquía sellada. Si un autor de una biblioteca añade un nuevo subtipo a una API pública, un consumidor que no haya actualizado su código puede encontrarse con una `MatchException` en tiempo de ejecución. Debido a este riesgo, los tipos sellados suelen ser más efectivos dentro de la implementación interna de un componente donde toda la base de código se recompila junta. Cuando se exponen como una API pública, añadir un nuevo subtipo constituye un cambio que rompe la compatibilidad y que puede requerir un aumento de versión mayor para asegurar que todos los consumidores estén al tanto del nuevo caso y actualicen sus emparejamientos de patrones en consecuencia.

Adicionalmente, el emparejamiento de patrones de Java continúa evolucionando con soporte para patrones recursivos y literales. Estas características permiten una lógica de emparejamiento más compleja, como patrones anidados (por ejemplo, emparejar un record que contiene otro record) y valores literales dentro de un switch. Estos avances tienen como objetivo acercar las capacidades expresivas de Java a las de lenguajes modernos como Kotlin y TypeScript, manteniendo al mismo tiempo los fundamentos orientados a objetos del lenguaje. Al combinar los tipos sellados con estos patrones avanzados, Java proporciona un marco para crear una lógica robusta y segura en cuanto a tipos que minimiza el riesgo de casos no manejados en el procesamiento de datos complejos.