By Shubham Aggarwal | 3/7/2017 | General |Beginners

Guide to Functional Interfaces in Java

Guide to Functional Interfaces in Java

This article will throw light on the latest Functional Interfaces introduced in Java 8. We will study what functional interfaces are and how we can use them to empower our application and make our code cleaner and faster.

 

We’ll run through about what Functional Interfaces are, how they couple with Lambda expressions to exhibit strong OOP behaviour and we will also study different Functional Interfaces introduced in detail with their methods. Let’s dive in now.

Functional Interfaces

Functional Interfaces focus on offering a single functionality through methods. Though these interfaces sounds new, every Java developer has used Functional Interfaces at least once during development. Some of the common interfaces are:

 

  • java.lang.Runnable
  • java.awt.event.ActionListener
  • java.util.Comparator
  • java.util.concurrent.Callable etc.

 

There is a common feature in all of the interfaces mentioned above—they all offer just a single method through their definition. These interfaces are also called Single Abstract Method interfaces (SAM Interfaces). A popular way in which these are used is by creating Anonymous Inner classes using these interfaces. The following code snippet describes an example:

 

 

public class AnonymousInnerClassTest {

 public static void main(String[] args) {

   new Thread(new Runnable() {

     @Override

     public void run() {

       System.out.print("A thread created and running on DiscoverSDK");

     }

   }).start();

 }

}

>>> A functional interface has exactly one abstract method.

 

In Java 8, a similar concept of SAM interfaces is recreated and is called Functional interfaces.

 

Lets try to have a look at a simple functional interface with only one abstract method:

 

 

@FunctionalInterface

public interface SimpleFuncInterface {

 public void doWork();

}

The interface can also declare the abstract methods from the java.lang.Object class, but still the interface can be called as a Functional Interface:

 

 

@FunctionalInterface

public interface SimpleFuncInterface {

 public void doWork();

 public String toString();

 public boolean equals(Object o);

}

>>> Instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

 

It is also worth noticing that the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a Functional Interface annotation is present on the interface declaration.

Features of Functional Interfaces

Some observations about SAM interfaces are:

  1. A functional interface has only one abstract method but it can have multiple default methods.
  2. @FunctionalInterface annotation is used to ensure an interface can’t have more than one abstract method. The use of this annotation is optional.
  3. The java.util.function package contains many built-in functional interfaces in Java 8.

Pre-Built Functional Interfaces

There are a lot of re-usable functional requirements that can be captured by functional interfaces and lambdas. The designers of Java 8 have captured the common use cases and created a library of functions for them. A new package called java.util.function was created to host these common functions.

 

There are a handful of these interfaces added to the library, which we’ll discuss in the next section.

Predicates

Class : java.util.Predicate

 

Predicate function is used for checking a condition. They are boolean-valued functions of one argument. The interface contains various default methods for composing predicates to complex logical terms (and, or, negate). It accepts a single argument to evaluate to a boolean result. It has a single method test which returns the boolean value. See the interface sample below which is a generic type accepting any type T:

@FunctionalInterface

public interface Predicate<T> {

 boolean test(T t);

}

From our knowledge of lambdas so far, we can deduce the lambda expression for this Predicate. Here are some examples of lambda expressions in code samples:

Predicate<String> predicate = (s) -> s.length() > 0;



predicate.test("DiscoverSDK");              // true

predicate.negate().test("DiscoverSDK");     // false



Predicate<Boolean> nonNull = Objects::nonNull;

Predicate<Boolean> isNull = Objects::isNull;



Predicate<String> isEmpty = String::isEmpty;

Predicate<String> isNotEmpty = isEmpty.negate();

 

Functions

Class : java.util.Function

 

A Function is a functional Interface whose primary and sole purpose in life is to return any result by working on a single input argument. It accepts an argument of type T and returns a result of type R, by applying specified logic on the input via the apply method. The interface definition is shown here:

 

 

// The T is the input argument while R is the return result

@FunctionalInterface

public interface Function<T, R> {

 R apply(T t);

}

One of the examples is shown in following code snippet:

 

// convert centigrade to fahrenheit

Function<Integer,Double> centigradeToFahrenheitInt = x -> new Double((x*9/5)+32);



// String to an integer

Function<String, Integer> stringToInt = x -> Integer.valueOf(x);



// tests

System.out.println("C to F:" + centigradeToFahrenheitInt.apply(centigrade));

System.out.println(" String to Int: " + stringToInt.apply("4"));

Did you notice the two arguments to the Function: String and Integer? This indicates that the function is expecting a String and returning the Integer.

Suppliers

Suppliers produce a result of a given generic type. Unlike Functions, Suppliers don't accept arguments. It’s definition interface is given as:

 

@FunctionalInterface

public interface Supplier<T> {

 T get();

}

Let’s look at one of the example code snippets now:

 

Supplier<Person> personSupplier = Person::new;

personSupplier.get();   // new Person

>>> Suppliers don't accept arguments.

 

There is no requirement that a new or distinct result be returned each time the supplier is invoked.

Consumers

Consumers represent operations to be performed on a single input argument. It’s interface definition is given as:

 

@FunctionalInterface

public interface Consumer<T> {

 void accept(T t);

}

Let’s have a look at another example for this interface:

 

Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);

greeter.accept(new Person("Discover", "SDK"));

Comparators

Comparators are well known from older versions of Java. Java 8 adds various default methods to the interface.

 

Let’s look at an example:

 

Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);


Person p1 = new Person("John", "Doe");

Person p2 = new Person("Java", "Wonderland");



comparator.compare(p1, p2);             // > 0

comparator.reversed().compare(p1, p2);  // < 0

Optionals

Optionals are not functional interfaces, instead it's a nifty utility to prevent NullPointerException. It's an important concept for the next section, so let's have a quick look at how Optionals work.

 

Optional is a simple container for a value which may be null or non-null. Think of a method which may return a non-null result but sometimes returns nothing. Instead of returning null you return an Optional in Java 8.

 

Optional<String> optional = Optional.of("foo");



optional.isPresent();           // true

optional.get();                 // "bam"

optional.orElse("bar");    // "bam"



optional.ifPresent((s) -> System.out.println(s.charAt(0)));     // "b"

Additionally, another question pops up. Can you override toString() and equals() method of a Functional Interface?

 

No, lambda expressions are used to express one method interfaces as if they are just functions. It's an element of functional languages that was implemented in Java (an OOP language).

 

To override toString, you must implement the interface in a class.

Interface with default methods vs Abstract class

You must think, if Functional Interfaces can contain default methods, what is the difference between Functional Interfaces and Abstract classes? Aren’t they the same now??

 

There are a few technical differences. Abstract classes can still do more in comparison to Java 8 interfaces:

  1. Abstract class can have a constructor.
  2. Abstract classes are more structured and can hold a state.

 

The good thing about this new feature of functional interfaces is that, where before we were forced to use an abstract class for the convenience methods, thus constraining the implementor to single inheritance, now we can have a really clean design with just the interface and a minimum of implementation effort forced on the programmer.

Conclusion

In this article we walked through the latest Functional Interfaces API, introduced in Java 8. We studied about what functional interfaces offer to us and how we can use them to empower our application and make our code cleaner and faster. In the java.util.Function package, there are over 45 functional interfaces present which are very useful once we become familiar with them. So go ahead and start using them to make better apps.

 

Check out my article on Abstract Classes in Java or

Visit our homepage to search and compare the best Java SDKs.

By Shubham Aggarwal | 3/7/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now