Skip to content

Functional interfaces: the single abstract method rule

โ˜• Java 17 ยท The One-Method Contract Behind Every Lambda ยท 1/3

Why a lambda needs a contract

m -> m.rating() > 8

This lambda has a parameter and a body, but no name and no type. On its own, Java can't tell what it's for. Its meaning comes from the type that receives it:

interface RatingRule {
    boolean check(Movie m);
}

RatingRule rule = m -> m.rating() > 8;

RatingRule has one method left to implement, check(). Java uses the lambda as its body: m is a Movie, and the result must be a boolean. This only works if there is exactly one blank to fill.

The SAM rule

An interface with exactly one abstract method is a functional interface. This is the Single Abstract Method rule, or SAM.

public interface RatingRule {
    boolean check(Movie m);              // the only abstract method
}

// option 1: a full class
public class TopRated implements RatingRule {
    public boolean check(Movie m) { return m.rating() >= 8.0; }
}

// option 2: a lambda, same job, one line
RatingRule rule = m -> m.rating() >= 8.0;

A class can still implement a functional interface; a lambda is just the shortest way to do it.

Inherited methods count

An interface inherits its parent's abstract methods. Count them too:

public interface Playable { void play(Episode e); }

public interface Bingeable extends Playable { }      // โœ… inherits play(): 1 abstract

public interface Rewindable extends Playable {       // โŒ play() + rewind(): 2 abstract
    void rewind(int seconds);
}

Rewindable is a valid interface, but not a functional one: a lambda can't implement two methods.

Methods with a body don't count

Since Java 8 and 9, interfaces can contain methods with code. None of them count:

public interface Recommender {
    List<Movie> suggest(User u);                 // abstract: counts

    default int limit() { return 10; }           // has a body
    static Recommender none() { return u -> List.of(); }
    private void log(String msg) { }             // has a body
}
Method kind Counts toward the rule?
abstract (no body) โœ… yes
default no: it has a body
static no
private / private static no

Recommender is functional: suggest() is its only abstract method. But an interface with only default, static or private methods has zero abstract methods, and zero isn't one: it's not functional.

Next: an annotation that checks the rule for you, and a loophole involving Object.

๐Ÿ’ป Code: Java17_Part_8_Functional_Programming on GitHub

Next: @FunctionalInterface and Object methods โ†’