Functional Interfaces Fundamentals


09 Apr 2018  Sergio Martin Rubio  1 min read.

Functional interfaces have only one abstract method, distinct from the public methods of Object.class (equals, hashCode, etc.), ensuring that the contract contains a single method.

Annotation

@FunctionalInterface
interface Foo {
	void method();
}

While the @FunctionalInterface annotation is not mandatory, it is highly recommended. This annotation allows the compiler to verify whether your interface is indeed functional. Moreover, using this annotation makes your architecture easier to understand.

Use Cases

Since the release of Java 8, functional interfaces have been particularly useful when combined with lambda expressions.

@FunctionalInterface
interface Foo {
	String method(String string);
}

Here’s an example of its usage:

Foo foo = string -> string + "world!";
System.out.println(foo.method("Hello "));

It is important to mention that Java 8 already provides some functional interfaces out-of-the-box in Function<T,R> from the java.util.function package. Therefore, in some cases, like the one explained previously, we can make use of them.

Function<String, String> function = string -> string + "world!";
System.out.println(function.apply("Hello "));

Default methods

Default methods are allowed in functional interfaces since they are not abstract methods.

@FunctionalInterface
interface Foo {
	String method(String string);
		
	default String defaultMethod() {
		return "Hello World!";
	}
}

Although you are allowed to define default methods in functional interfaces, it is not a good practice to overuse this technique. Default methods might clash with each other when your interface extends several interfaces with default methods.

Image by donterase from Pixabay