Explanation
Every interface that only offers one (abstract) method, i.e. without implementation, is a so called functional interface.
Being it explicitly or implicitly.
The annotation @FunctionalInterface
is, like @Override
, optional, if you want to create a functional interface.
So if you declare an interface @FunctionalInterface
, but it actually has more than just one such method, the compiler helps you and prevents compilation with an error. Telling you that you violated your own intention.
If you do not have the annotation, it will compile, but it is not a functional interface anymore. This could be a bug to you, because your intention was to create a functional interface. Note that if you are actually using the interface in an environment where a functional interface is actually required, like for a lambda, it would obviously not compile anymore as soon as another method is added to the interface.
Here are some examples:
// is a functional interface
interface Foo {
void bar();
}
// is a functional interface
@FunctionalInterface
interface Foo {
void bar();
}
// is not a functional interface
interface Foo {
void bar();
void baz();
}
// does not compile
@FunctionalInterface
interface Foo {
void bar();
void baz();
}
Use
It is to make your intention clear to the compiler, other team members and your future self. That way, the compiler can help you spot bugs in case you mess up.
Another scenario might be if you are working in a team and design an interface. If you do not clearly mark this interface as functional interface, either by the annotation or with a comment/documentation, another team member might not know your intention and add more methods to it.
This is especially important if you are a library designer, i.e. writing code that is to be used by other, external, people. If you mark your interface @FunctionalInterface
, it is a promise to them that you intent to keep it like that. So they can safely use it for lambdas, for example. Without fearing that their code will break as soon as you ship an update to your library.
The opposite case is true as well. If they spot an interface of yours that only has one method, but is not explicitly annotated, they will understand that this is not meant to be used as functional interface, eventhough it currently is one. Thus, they will not use it for lambdas, although they could, since you might change it in a future update.
Details
You can read about the precise definitions in JLS§9.8. Functional Interfaces:
A functional interface is an interface that has just one abstract method (aside from the methods of Object), and thus represents a single function contract. This "single" method may take the form of multiple abstract methods with override-equivalent signatures inherited from superinterfaces; in this case, the inherited methods logically represent a single method.
And JLS§9.6.4.9. @FunctionalInterface:
The annotation type FunctionalInterface is used to indicate that an interface is meant to be a functional interface (§9.8). It facilitates early detection of inappropriate method declarations appearing in or inherited by an interface that is meant to be functional.
It is a compile-time error if an interface declaration is annotated with @FunctionalInterface but is not, in fact, a functional interface.
Because some interfaces are functional incidentally, it is not necessary or desirable that all declarations of functional interfaces be annotated with @FunctionalInterface.
The last paragraph here is especially important. I.e. you might have created a functional interface incidentally and plan to add more to it later. So people should not mistake this and use it with lambdas, otherwise their code will break later, when you add more methods.
Note
As mentioned before, the @Override
tag works the same, but for overriding methods. So you can also override methods without it. But if you use it and maybe made a typo, i.e. you are not actually overriding something, the compiler will help you spot this issue immediately.