189

I came across a new term in Java 8: "functional interface". I could only find one use of it while working with lambda expressions.

Java 8 provides some built-in functional interfaces and if we want to define any functional interface then we can make use of the @FunctionalInterface annotation. It will allow us to declare only a single method in the interface.

For example:

@FunctionalInterface
interface MathOperation {
    int operation(int a, int b);
}

How useful it is in Java 8 other than just working with lambda expressions?

(The question here is different from the one I asked. It is asking why we need functional interfaces while working with lambda expressions. My question is: What are the other uses of functional interfaces besides use with lambda expressions?)

logi-kal
  • 7,107
  • 6
  • 31
  • 43
Madhusudan
  • 4,637
  • 12
  • 55
  • 86
  • 1
    It looks duplcate to this link. They also talk about why there should be only one method in Functional Interface. http://stackoverflow.com/questions/33010594/why-do-i-need-a-functional-interface-to-work-with-lambdas – Kulbhushan Singh Apr 27 '16 at 06:29
  • 1
    @KulbhushanSingh I saw this question before posting... Both questions sense difference... – Madhusudan Apr 27 '16 at 06:32

11 Answers11

144

@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

Andrea Bergonzo
  • 3,983
  • 4
  • 19
  • 31
Sergii Bishyr
  • 8,331
  • 6
  • 40
  • 69
  • 47
    To be more precise, you have to have *exactly one* abstract method that doesn’t override a method in `java.lang.Object` in a functional interface. – Holger Apr 27 '16 at 08:04
  • 9
    …and it’s slightly different to “not have more than one `public` method besides `static` and `default`”… – Holger Apr 27 '16 at 08:12
  • @lwpro2 a typo. Sure it was about `obj -> obj.doSomething(anyObj)`. Thanks for noticing! – Sergii Bishyr Jul 23 '17 at 15:28
  • @lwpro2 but even with this I'm unable to reproduce the issue in most recent versions of java – Sergii Bishyr Jul 23 '17 at 15:37
  • What if a method overridden from Object is redeclared in a manner incompatible with Object's implementation -- e.g. narrowing the return type of clone()? – Pr0methean Aug 18 '17 at 00:41
  • 5
    Still don't understand any point of having it. Why would anyone on earth bothers checking how many methods does his/her interface has. Marker interfaces still have a point and a specific purpose. The documentation and the answer only explain what it does, not how is it of any use at all. And "use" is exactly what the OP asked. So I wouldn't recommend this answer. – saran3h Feb 22 '18 at 17:48
  • @saran3h thanks for your comment. The concept of the functional interface is completely different question. The point of having this annotation on top of your interface is to make it clear to the client of this interface how it is used, and make sure no one add more methods consequently breaking the clients of your interface. – Sergii Bishyr Feb 23 '18 at 09:15
  • @Sergii Bishyr But without declaring FunctionalInterface annotation on the interface, we have got the compilation errors if we declare more than one method in the interface and using lambda expressions. Then what is the use of FunctionalInterface annotation? – VNT Apr 27 '18 at 14:06
  • 1
    @VNT the compilation error get the clients of this interface, but not the interface itself can change. With this annotation the compilation error is on the interface, so you make sure that nobody will break the clients of your interface. – Sergii Bishyr Apr 27 '18 at 16:21
  • 3
    This shows how to use them but doesn't explain why we need them though. – sheikh Aug 10 '19 at 03:04
  • Don't you think, the compiler will anyways throw an error in case of the interface is not compliant. Then why even we should use @FunctionalInterface? Just wondering... – surajs1n Jul 05 '20 at 08:27
  • It’s true for the case when you are the client of your own interface. But not for the case when it’s part of a library. Also, usually the software projects is written by many people, so this is a way to tell other developers that this interface is can be used as a lambda, so it’s better not to add another abstract method – Sergii Bishyr Jul 05 '20 at 15:36
25

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.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
  • Might just be asking for a little too much or irrelevant(you can choose not to answer), but what would you suggest when someone created a utility `public static String generateTaskId()` versus to make it more "functional" someone else chose to write it as `public class TaskIdSupplier implements Supplier` with the `get` method using the existing generation implementation. Is that a misuse of functional interfaces, especially reusing the `Supplier` from the JDK built-in? PS: I couldn't find a better place/Q&A to ask this. Happy to migrate if you could suggest. – Naman Jan 09 '20 at 17:31
  • 1
    @Naman you are not making the utility method more functional when you create a named class `TaskIdSupplier`. Now, the question is why you created the named class. There are scenarios where such a named type is needed, e.g. when you want to support finding the implementation via `ServiceLoader`. There is nothing wrong with letting it implement `Supplier` then. But when you don’t need it, don’t create it. When you only need a `Supplier`, it’s already sufficient to use `DeclaringClass::generateTaskId` and eliminating the need for an explicit class is the point of this language feature. – Holger Jan 09 '20 at 17:42
  • To be honest, I was looking towards a justification for a recommendation that I was passing on. For some reason at work I didn't really felt that the `TaskIdSupplier` implementation was worth the effort, but then the concept of `ServiceLoader` totally skipped off my mind. Encountered a few questions during these discussions we were having such as *What is the use of `Supplier`'s `public` existence when one can go ahead and develop their own interfaces?* and *Why not have `public static Supplier TASK_ID_SUPPLIER = () ->...` as a global constant?*. (1/2) – Naman Jan 09 '20 at 18:02
  • All of that seems to be simple and basic, while in the course of implementation to make a decision or while designing the services, it seems tough to provide justifications over such questions and that certainly needs a hands-on with a variety of language features. – Naman Jan 09 '20 at 18:07
  • 1
    @Naman the idiomatic way to represent functions in Java are methods and evaluating those functions is identical to invoking them. Never should a developer be forced to do `variable.genericMethodName(args)` instead of `meaningfulMethodName(args)`. Using a class type to represent a function, whether via lambda expression/ method reference or a manually created class, is only a vehicle *to pass the function around* (in the absence of true function types in Java). This should only be done when needed. – Holger Jan 09 '20 at 18:22
  • 1
    When you have a small code fragment only being passed around, you may create a lambda expression encapsulating it. Whenever there’s also a need to invoke it like a method (this includes scenarios with a need for testing, when the code fragment is not trivial), create a named method that can be invoked and use a method reference or a lambda expression/ explicit class encapsulating a call, to pass it around when needed. Constants are only useful when you don’t trust the efficiency of lambda expressions or method references embedded in your code, in other words, they are almost never needed. – Holger Jan 09 '20 at 18:22
15

As others have said, a functional interface is an interface which exposes one method. It may have more than one method, but all of the others must have a default implementation. The reason it's called a "functional interface" is because it effectively acts as a function. Since you can pass interfaces as parameters, it means that functions are now "first-class citizens" like in functional programming languages. This has many benefits, and you'll see them quite a lot when using the Stream API. Of course, lambda expressions are the main obvious use for them.

Sina Madani
  • 1,246
  • 3
  • 15
  • 27
14

Not at all. Lambda expressions are the one and only point of that annotation.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • 7
    Well, lamdbas work without the annotation as well. It's an assertion just like `@Override` to let the compiler know that you intended to write something that was "functional" (and get an error if you slipped). – Thilo Apr 27 '16 at 06:34
  • 2
    Straight to the point and the correct answer, though a bit short. I took the time to add a [more elaborated answer](http://stackoverflow.com/a/36884458/2711488) saying the same thing with more words… – Holger Apr 27 '16 at 08:41
8

A lambda expression can be assigned to a functional interface type, but so can method references, and anonymous classes.

One nice thing about the specific functional interfaces in java.util.function is that they can be composed to create new functions (like Function.andThen and Function.compose, Predicate.and, etc.) due to the handy default methods they contain.

Hank D
  • 6,271
  • 2
  • 26
  • 35
6

An interface with only one abstract method is called Functional Interface. It is not mandatory to use @FunctionalInterface, but it’s best practice to use it with functional interfaces to avoid addition of extra methods accidentally. If the interface is annotated with @FunctionalInterface annotation and we try to have more than one abstract method, it throws compiler error.

package com.akhi;
    @FunctionalInterface
    public interface FucnctionalDemo {

      void letsDoSomething();
      //void letsGo();      //invalid because another abstract method does not allow
      public String toString();    // valid because toString from Object 
      public boolean equals(Object o); //valid

      public static int sum(int a,int b)   // valid because method static
        {   
            return a+b;
        }
        public default int sub(int a,int b)   //valid because method default
        {
            return a-b;
        }
    }
Akhilesh
  • 89
  • 1
  • 6
5

Functional Interface:

  • Introduced in Java 8
  • Interface that contains a "single abstract" method.

Example 1:

   interface CalcArea {   // --functional interface
        double calcArea(double rad);
    }           

Example 2:

interface CalcGeometry { // --functional interface
    double calcArea(double rad);
    default double calcPeri(double rad) {
        return 0.0;
    }
}       

Example 3:

interface CalcGeometry {  // -- not functional interface
    double calcArea(double rad);
    double calcPeri(double rad);
}   

Java8 annotation -- @FunctionalInterface

  • Annotation check that interface contains only one abstract method. If not, raise error.
  • Even though @FunctionalInterface missing, it is still functional interface (if having single abstract method). The annotation helps avoid mistakes.
  • Functional interface may have additional static & default methods.
  • e.g. Iterable<>, Comparable<>, Comparator<>.

Applications of Functional Interface:

  • Method references
  • Lambda Expression
  • Constructor references

To learn functional interfaces, learn first default methods in interface, and after learning functional interface, it will be easy to you to understand method reference and lambda expression

zeko868
  • 163
  • 1
  • 3
  • 10
Ketan
  • 89
  • 2
  • 8
  • Should your first two examples have 'abstract' keyword to it? – sofs1 Dec 24 '18 at 10:43
  • 1
    @sofs1 Methods declared in interfaces are by default both public and abstract. You have to use abstract keyword in case of methods in abstract class. However it is fine to use abstract keyword for methods in interface also. They have permitted it for compatibility of older java version but it is discouraged. – Ketan Jan 02 '19 at 05:15
2

You can use lambda in Java 8

public static void main(String[] args) {
    tentimes(inputPrm - > System.out.println(inputPrm));
    //tentimes(System.out::println);  // You can also replace lambda with static method reference
}

public static void tentimes(Consumer myFunction) {
    for (int i = 0; i < 10; i++)
        myFunction.accept("hello");
}

For further info about Java Lambdas and FunctionalInterfaces

Akiner Alkan
  • 6,145
  • 3
  • 32
  • 68
1

@FunctionalInterface is a new annotation are released with Java 8 and provide target types for lambda expressions and it used on compilation time checking of your code.

When you want to use it :

1- Your interface must not have more than one abstract methods, otherwise compilation error will be given.

1- Your interface Should be pure, which means functional interface is intended to be implemented by stateless classes, exmple of pure is Comparator interface because its not depend on the implementers state, in this case No compilation error will be given, but in many cases you will not be able to use lambda with this kind of interfaces

The java.util.function package contains various general purpose functional interfaces such as Predicate, Consumer, Function, and Supplier.

Also please note that you can use lambdas without this annotation.

Ahmad Al-Kurdi
  • 2,248
  • 3
  • 23
  • 39
1

Beside other answers, I think the main reason to "why using Functional Interface other than directly with lambda expressions" can be related to nature of Java language which is Object Oriented.

The main attributes of Lambda expressions are: 1. They can be passed around 2. and they can executed in future in specific time (several times). Now to support this feature in languages, some other languages deal simply with this matter.

For instance in Java Script, a function (Anonymous function, or Function literals) can be addressed as a object. So, you can create them simply and also they can be assigned to a variable and so forth. For example:

var myFunction = function (...) {
    ...;
}
alert(myFunction(...));

or via ES6, you can use an arrow function.

const myFunction = ... => ...

Up to now, Java language designers have not accepted to handle mentioned features via these manner (functional programming techniques). They believe that Java language is Object Oriented and therefore they should solve this problem via Object Oriented techniques. They don't want to miss simplicity and consistency of Java language.

Therefore, they use interfaces, as when an object of an interface with just one method (I mean functional interface) is need you can replace it with a lambda expression. Such as:

ActionListener listener = event -> ...;
MMKarami
  • 1,144
  • 11
  • 14
1

Functional Interfaces: An interface is called a functional interface if it has a single abstract method irrespective of the number of default or static methods. Functional Interface are use for lamda expression. Runnable, Callable, Comparable, Comparator are few examples of Functional Interface.

KeyNotes:

  • Annotation @FunctionalInterface is used(Optional).
  • It should have only 1 abstract method(irrespective of number of default and static methods).
  • Two abstract method gives compilation error(Provider @FunctionalInterface annotation is used).

This thread talks more in detail about what benefit functional Interface gives over anonymous class and how to use them.

tgallei
  • 827
  • 3
  • 13
  • 22
yog_05
  • 11
  • 3