Java – @FunctionalInterface benefits in a staged builder

@FunctionalInterface benefits in a staged builder… here is a solution to the problem.

@FunctionalInterface benefits in a staged builder

Introduction

While searching the web, I stumbled upon Benoit Tellier’s blog post, Next level Java 8 staged builders , In it, he shares variations of the staged builder pattern for certain use cases.

I noticed that the stage is annotated with @FunctionalInterface. Here’s an example from his post (no tricks):

public static class MailboxCreatedBuilder {
    @FunctionalInterface
    public interface RequireUser {
        RequireSessionId user(User user);
    }

@FunctionalInterface
    public interface RequireSessionId {
        RequireMailboxId sessionId(MailboxSession.SessionId sessionId);
    }

@FunctionalInterface
    public interface RequireMailboxId {
        FinalStage mailboxId(MailboxId mailboxId);
    }

public static class FinalStage {
        ...
        ...
    }

public static RequireUser builder() {
        return user -> sessionId -> mailboxId -> new FinalStage(user, sessionId, mailboxId);
    }
}

This comment limits the number of methods a stage can have to one, plus overloaded methods with default implementations. Anyway, it might be a good idea to deal with one property per stage, but for my current needs, I’d like to have multiple methods and implementations in separate classes.

Question

This makes me wonder: should my stage also have @FunctionalInterface? What are the benefits of such a builder/how can I use it in functional style programming?

Edit

Based on the

comments below on this issue, it turns out that what I really want to know is what the requirements/benefits are for having the stage adhere to the functional interface contract (regardless of optional annotations).

Solution

The stage type required by a single method is used to force the caller to provide the desired value, enforced by the compiler (it also enforces a specific order). The FinalStage class then has all optional methods.

In this case, after calling builder(), you must call user(…), then sessionId(…), then mailboxId(...), and finally FinalStage Any optional methods defined in :

MailboxCreatedBuilder.builder()
        .user(...)
        .sessionId(...)
        .mailboxId(...)
        ...
        .build();

Related Problems and Solutions