@FunctionalInterface annotation is useful for compilation time checking of your code. You cannot have more than one method besides static, default and abstract methods that override methods in Object in your @FunctionalInterface or any other interface used as a functional interface.
But you can use lambdas without this annotation as well as you can override methods without @Override annotation.
From docs
a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere
This can be used in lambda expression:
public interface Foo {
public void doSomething();
}
This cannot be used in lambda expression:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
But this will give compilation error:
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Answer from Sergii Bishyr on Stack OverflowInvalid '@FunctionalInterface' annotation; Foo is not a functional interface
lambda - What are functional interfaces used for in Java 8? - Stack Overflow
Real world example of using a functional interface in Java - Stack Overflow
Guide to Functional Interfaces in Java
Java 8's new functional interface Predicate...
Videos
@FunctionalInterface annotation is useful for compilation time checking of your code. You cannot have more than one method besides static, default and abstract methods that override methods in Object in your @FunctionalInterface or any other interface used as a functional interface.
But you can use lambdas without this annotation as well as you can override methods without @Override annotation.
From docs
a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere
This can be used in lambda expression:
public interface Foo {
public void doSomething();
}
This cannot be used in lambda expression:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
But this will give compilation error:
@FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Invalid '@FunctionalInterface' annotation; Foo is not a functional interface
The documentation makes indeed a difference between the purpose
An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification.
and the use case
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
whose wording does not preclude other use cases in general. Since the primary purpose is to indicate a functional interface, your actual question boils down to “Are there other use cases for functional interfaces other than lambda expressions and method/constructor references?”
Since functional interface is a Java language construct defined by the Java Language Specification, only that specification can answer that question:
JLS §9.8. Functional Interfaces:
…
In addition to the usual process of creating an interface instance by declaring and instantiating a class (§15.9), instances of functional interfaces can be created with method reference expressions and lambda expressions (§15.13, §15.27).
So the Java Language Specification doesn’t say otherwise, the only use case mentioned in that section is that of creating interface instances with method reference expressions and lambda expressions. (This includes constructor references as they are noted as one form of method reference expression in the specification).
So in one sentence, no, there is no other use case for it in Java 8.
First of all annotation @FunctionalInterface is used by Java's built-in functional interfaces Predicate,Function,Consumer, etc...
From the other hand you may want to create your custom one like the following:
@FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T t) throws CustomException;
}
Then you can use it as a method parameter:
public <T, R> void doSomething(T value, ThrowingConsumer<T, R> consumer) {
// ...
}
And then call it like this:
doSomething(someValue, this::customConsumerMethodThrowingAnException);
It is worth to mention that @FunctionalInterface is not required. The compiler will be perfectly fine with any interface meeting the requirements.
The compiler treats it in a way similar to dealing with @Override annotation. The code compiles even without it. But once added it makes the code clearer and safer for the ones who will maintain the code in the future.
We've always had functional interfaces before JDK8 but no lambdas, method references etc.
As of JDK8, they provide a target type for lambda expressions, method references and in turn, have better readability and more compact code.
Example, prior to Java-8 if you wanted to provide some logic that will be executed each time a Button component is clicked you'd do:
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");
}
});
This is bulky, hard to read and not compact enough. because EventHandler is by definition a functional interface i.e. it has a SAM as of jdk8 you can now do:
btn.setOnAction(event -> System.out.println("Hello World!"));
You only see the part of the code you care about i.e. the logic to be executed when the button is clicked.
Further, due to the fact that we can use functional interfaces as target types for lambda expressions & methods references, this would be useful when:
- passing a comparator to a sort method e.g.
List.sort,Stream.sorted,Collections.sortetc. - passing a block of code to run a task in a separate thread
etc...
while keeping the code readable, compact and concise.
Functional interfaces are used extensively in the Java-stream API.
There's no reason for you to create your own functional interface except there's not one that meets your requirements from java.util.function or the name of the functional interface is not as readable so thus you may create your own.
There's also a @FunctionalInterface annotation recommended to be used but not required whenever you're creating a functional interface (the standard library uses this a lot).
This enables the compiler to check that the annotated entity is an interface with a single abstract method otherwise gives an error.
This is also quite helpful in being able to catch errors when refactoring your code.