skip to content

What is a functional interface and what is a marker interface? How do they relate to interface declaration?

level: seniorimportance: should knowfreq 55%

answer

  1. Functional = exactly one abstract method (SAM) → lambda
  2. @FunctionalInterface enforces the shape (optional)
  3. default/static methods don't count toward the one
  4. Marker = zero members, tags a type for instanceof
  5. Serializable/Cloneable are markers; Runnable/Comparator are functional

basics

~20 s

A functional interface has exactly one abstract method, so it can be implemented with a lambda (e.g. Runnable). A marker interface has no methods at all; it just tags a class with a capability (e.g. Serializable).

solid answer

~50 s

Both are special shapes of interface declaration. A **functional interface** declares exactly one abstract method (a 'single abstract method' or SAM type); because there's one method to fill, you can implement it with a **lambda** or method reference instead of an anonymous class. Default and static methods don't count toward the one-abstract-method rule. The `@FunctionalInterface` annotation is optional but makes the compiler enforce the single-method shape. Examples: `Runnable`, `Comparator`, `Function`. A **marker interface** declares *no* members at all; it exists purely to tag a type so code (or the JVM) can check `instanceof` and change behavior — classic examples are `Serializable` and `Cloneable`. Both illustrate that an interface's *member count* changes how it's used: zero members = a tag, one abstract member = a lambda target, many = a conventional contract. Today marker interfaces are often replaced by annotations, but those checked at runtime via the type system (like `Serializable`) remain useful.

code

java · 13 lines
java
@FunctionalInterface
interface Transformer {
    String apply(String in);                 // single abstract method
    default String twice(String in) {        // allowed, doesn't break SAM
        return apply(apply(in));
    }
}

Transformer up = s -> s.toUpperCase();        // lambda implements it

interface Trusted {}                          // marker interface: no members
Object o = new Object();
boolean trusted = o instanceof Trusted;       // behavior keyed off the tag

go deeper

for a junior

Recognizes that Runnable-style one-method interfaces work with lambdas and that Serializable is a tag.

for a middle

Defines SAM precisely (default/static don't count) and names the role of @FunctionalInterface and marker examples.

for a senior

Compares marker interfaces vs annotations and explains how member count shapes interface idioms.

for a principal

Designs lambda-friendly APIs and weighs type-system markers vs annotation metadata for framework contracts.

## Background: what counts as an 'abstract method' Recall an interface can hold **abstract methods** (no body), **default** methods (a body, inherited), and **static** methods (a body, called on the interface). Only **abstract** methods are part of the must-implement contract. This distinction is what defines the two special shapes below. ## Functional interface (SAM type) A **functional interface** is an interface with **exactly one abstract method** — also called a Single Abstract Method (SAM) type. Default and static methods do not count, so an interface can have many of those and still be functional. ```java @FunctionalInterface interface Greeter { String greet(String name); // the single abstract method default String shout(String n) { return greet(n).toUpperCase(); } // doesn't count } ``` Why it matters: because there is exactly one method to implement, Java lets you supply the implementation as a **lambda expression** or **method reference**, which is far more concise than an anonymous class: ```java Greeter g = name -> "Hi " + name; // lambda implements greet(...) Greeter g2 = String::toUpperCase; // (illustrative) method reference ``` The optional **`@FunctionalInterface`** annotation tells the compiler to *verify* the interface has exactly one abstract method and fail compilation otherwise — a safety net so a future edit doesn't accidentally break lambda usage. The annotation is not required for an interface to be functional; it just enforces the shape. The `java.util.function` package (`Function`, `Predicate`, `Supplier`, `Consumer`, …) and classics like `Runnable`, `Callable`, `Comparator` are all functional interfaces. ## Marker interface A **marker interface** declares **no methods and no constants** at all. It carries no behavior — its only job is to **tag** (mark) a type so that other code can detect the tag and treat tagged objects specially, typically via `instanceof`. ```java interface Auditable {} // a marker, no members if (obj instanceof Auditable) { // behavior keyed off the tag audit(obj); } ``` The JDK's `java.io.Serializable` and `Cloneable` are markers: the JVM/`ObjectOutputStream` checks `instanceof Serializable` before serializing and throws `NotSerializableException` otherwise. The marker grants a *capability* through the type system rather than through a method. ## Markers vs annotations Since Java 5, **annotations** (e.g. `@Deprecated`) often replace marker interfaces for metadata. But marker *interfaces* still have advantages: they are part of the **type system**, so the compiler can enforce that a method only accepts marked types (`void save(Serializable s)`), and `instanceof` checks are cheap. Annotations are better when the marker shouldn't constrain the type hierarchy or when you need parameters. Rule of thumb: use a marker interface when you want a *type constraint* you can check at compile time; use an annotation for pure metadata. ## The unifying idea The number and kind of members in an interface declaration determine its idiom: - **0 members** → marker interface (a tag). - **exactly 1 abstract method** → functional interface (a lambda target). - **many members** → a conventional contract. All three are just interfaces; the shape drives the usage.

  • Does adding a default method to a functional interface break it?
    No. Only abstract methods count toward the single-abstract-method rule, so an interface can have many default/static methods and still be functional and lambda-compatible.
  • When would you use a marker interface instead of an annotation?
    When you want the marker to be part of the type system — e.g. so a method signature can require the marked type (`void f(Serializable s)`) and the compiler enforces it, or so `instanceof` checks apply. Annotations are better for pure metadata or when you need attributes.

A functional interface is a one-line job (a single task you can hand to a lambda); a marker interface is a badge you pin on someone that grants access but defines no duties.

saying these in an interview costs you the question

  • Saying a functional interface can have only one method total (default/static methods are allowed)
  • Believing @FunctionalInterface is required for lambda use
  • Thinking marker interfaces declare methods
  • Confusing marker interfaces with annotations as identical

context