What are functional interfaces used for in Java 8?
@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
Purpose of Functional Interfaces in Java8
Obviously you can skip using these new interfaces and roll your own with better names. There are some considerations though:
- You will not be able to use custom interface in some other JDK API unless your custom interface extends one of built-ins.
- If you always roll with your own, at some point you will come across a case where you can't think of a good name. For example, I'd argue that
CheckPerson
isn't really a good name for its purpose, although that's subjective.
Most builtin interfaces also define some other API. For example, Predicate
defines or(Predicate)
, and(Predicate)
and negate()
.
Function
defines andThen(Function)
and compose(Function)
, etc.
It's not particularly exciting, until it is: using methods other than abstract ones on functions allows for easier composition, strategy selections and many more, such as (using style suggested in this article):
Before:
class PersonPredicate {
public Predicate<Person> isAdultMale() {
return p ->
p.getAge() > ADULT
&& p.getSex() == SexEnum.MALE;
}
}
Might just become this, which is more reusable in the end:
class PersonPredicate {
public Predicate<Person> isAdultMale() {
return isAdult().and(isMale());
}
publci Predicate<Person> isAdultFemale() {
return isAdult().and(isFemale());
}
public Predicate<Person> isAdult() {
return p -> p.getAge() > ADULT;
}
public Predicate<Person> isMale() {
return isSex(SexEnum.MALE);
}
public Predicate<Person> isFemale() {
return isSex(SexEnum.FEMALE);
}
public Predicate<Person> isSex(SexEnum sex) {
return p -> p.getSex() == sex;
}
}
Functional interfaces introduced in java 8
While all of these interfaces existed prior to Java 8, 2 of them - Runnable
and Callable
- were annotated as @FunctionalInterface
since Java 8. That said, this annotation is informative, and even without it, they can be used as functional interfaces (which means they can be implemented by a lambda expression or a method reference) since Java 8.
The other two are not functional interfaces, since they have multiple abstract methods.
Java8: About Functional Interface
You are using the Lambda syntax to implement the getCar()
method of the Rideable interface, where the following anonymous class program is omitted using Lambda's concise syntax:
Rideable rideable = new Rideable() {
@Override
public Car getCar(String name) {
return new Car(name);
}
};
This is Java 7 code. You can achieve the same thing using using Lambda expression:
Rideable rider = name -> new Car(name);
Or as in your example, using method reference:
Rideable rider = Car::new;
As a result, the getCar(String)
method of the Rideable object can be used as a new Car(String)
.
And as an answer to your question, you are creating an instance of Car
class that implements the Rideable interface. This is another way you can implement an interface without using implement
keyword.
If you are thinking of:
Car auto = Car("MyCar")::new;
or
Car auto = Car::new;
Car vehicle = auto::getCar("MyCar");
or
Car vehicle = Rideable::new::getCar("MyCar");
All these examples are wrong
approaches. I gave you this examples because these are common mistakes that can be made when we are speaking about Lambda expressions or method reference.
Functional Interface Implementations and use cases
Why would I have interface with only one abstract method? What would be the use case of having only single abstract method in my interface?
To facilitate the use of lambda expressions , which are nameless functions.
Lambda expressions make code expressive and reduce clutter. It also makes code more readable. This is based my experience working with lambda expressions.
What are the advantages of Java Functional Interfaces?
Your questions could be answered if you read manual about functional interfaces and lambdas.
Just take a look on difference between lambda expression and usual anonymous class creation. Both variables can be used the same way.
//using anonymous class
Predicate<String> isStringEmptyObj = new Predicate<String>() {
@Override
public boolean test(String o) {
return o.isEmpty();
}
};
System.out.println(isStringEmptyObj.negate().test("asd"));
//using lambda with reference to existing String object method
Predicate<String> isStringEmpty = String::isEmpty;
System.out.println(isStringEmpty.negate().test("asd"));
Definition of Functional Interface in Java 8
It is true that the Comparator
interface has 2 abstract methods. But one of them is equals
, which overrides the equals
method defined in the Object
class, and this method doesn't count.
From @FunctionalInterface
:
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 fromjava.lang.Object
or elsewhere.
As such, this makes the Comparator
interface a functional interface where the functional method is compare(o1, o2)
.
The lambda expression (a, b) -> a > b ? -1 : 1
complies with that contract: it declares 2 parameters and return an int
.
Related Topics
Adding External Library to Artifact Jar in Intellij Idea
How to Implement Rest Token-Based Authentication With Jax-Rs and Jersey
How to Tell Gradle to Use Specific Jdk Version
How Can a Java Program Get Its Own Process Id
How to Read and Write Excel File
Why Does Java'S Hashcode() in String Use 31 as a Multiplier
Javac Is Not Recognized as an Internal or External Command, Operable Program or Batch File
Getresourceasstream Returns Null
String Is Immutable. What Exactly Is the Meaning
How to Do a Deep Copy of a 2D Array in Java
Split String to Equal Length Substrings in Java
Java Error: Comparison Method Violates Its General Contract
Sort Objects in Arraylist by Date
How to Turn a List of Lists into a List in Java 8
Java.Util.Date VS Java.Sql.Date
Received Fatal Alert: Handshake_Failure Through Sslhandshakeexception