Marker & Sealed Interfaces
Marker & Sealed Interfaces
Not every interface exists to describe behaviour through method contracts. Two specialised categories — marker interfaces and sealed interfaces — solve fundamentally different problems: one attaches metadata to a class, the other restricts which classes are permitted to implement an interface at all. Both patterns appear in real Java code, so understanding when and why to use each is essential.
Marker Interfaces
A marker interface has no methods. Its only purpose is to tag a class so that other code — typically a framework or the JVM itself — can detect the tag at runtime using instanceof or reflection.
When the JVM's serialisation mechanism receives an object, it checks obj instanceof Serializable before proceeding. If the class was not tagged, a NotSerializableException is thrown. The interface carries no method signature; all the real serialisation logic lives in the JVM and in ObjectOutputStream.
Other well-known JDK marker interfaces include Cloneable (enables the protected Object.clone() copy mechanism) and RandomAccess (signals that a List supports O(1) indexed access, allowing algorithms to pick a faster path).
Writing Your Own Marker Interface
You can define a marker interface to attach semantic meaning to classes in your own application:
@Idempotent can carry the same metadata with less ceremony and can additionally hold attributes (e.g. @Idempotent(retries = 3)). For new code, prefer annotations over marker interfaces unless you genuinely need a type-system check via instanceof or a generic bound like <T extends Idempotent>.
Sealed Interfaces (Java 17)
A sealed interface explicitly lists every class (or interface) that is permitted to implement it. Any class not on the list is a compile-time error. This gives the library author precise control over the type hierarchy.
Each permitted class must be declared in one of three ways:
final— closes the hierarchy completely; no further subclassing.sealed— the permitted class itself restricts its own subtypes.non-sealed— reopens the hierarchy; anyone may extend or implement this class.
Why Sealing Matters: Exhaustive Pattern Matching
The real payoff of sealed interfaces is with switch expressions introduced in Java 17+. Because the compiler knows every possible implementor, it can verify that your switch is exhaustive — no default branch required:
If you later add a Pentagon to the permits list, every switch on Shape that is missing the Pentagon case becomes a compile error — the compiler guides you to every call site that needs updating.
final, so they satisfy the sealed contract perfectly:
Sealed Interfaces vs Enums
An enum is perfect when each variant carries no extra data and you want a fixed set of constants. A sealed interface is the right choice when different variants carry different data shapes — for example Triangle has two measurements while Circle has one. The two features complement each other and can even be combined: an enum can implement a sealed interface to become one of its permitted variants.
Summary
Marker interfaces attach a tag to a class that runtime code can detect via instanceof; the JDK uses this for Serializable, Cloneable, and RandomAccess. For new code, annotations are often a cleaner alternative unless you need a type-system constraint. Sealed interfaces, added in Java 17, restrict who may implement an interface, turning the compiler into a guardian of your type hierarchy and enabling exhaustive pattern matching in switch expressions — a powerful tool for modelling closed sets of related types.