Java 8 introduces java.util.function containing a set of interfaces which are target types for lambda expressions and method references. Each interface contains only one abstract method, called the functional method .
// functional/FunctionalAnnotation.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
@FunctionalInterface
interface Functional {
String goodbye(String arg);
}
interface FunctionalNoAnn {
String goodbye(String arg);
}
/*
@FunctionalInterface // [1]
interface NotFunctional {
String goodbye(String arg);
String hello(String arg);
}
Produces error message:
NotFunctional is not a functional interface
multiple non-overriding abstract methods
found in interface NotFunctional
*/
public class FunctionalAnnotation {
public String goodbye(String arg) {
return "Goodbye, " + arg;
}
public static void main(String[] args) {
FunctionalAnnotation fa = new FunctionalAnnotation();
Functional f = fa::goodbye;
FunctionalNoAnn fna = fa::goodbye;
// Functional fac = fa; // Incompatible
Functional fl = a -> "Goodbye, " + a;
FunctionalNoAnn fnal = a -> "Goodbye, " + a;
}
}
The @FunctionalInterface annotation is optional; Java treats both Functional and FunctionalNoAnn as functional interfaces in main().
[1] ' error:
functional/FunctionalAnnotation.java:15: error: Unexpected @FunctionalInterface annotation
@FunctionalInterface
^
NotFunctional is not a functional interface
multiple non-overriding abstract methods found in interface NotFunctional
1 error
The solution is keeping one of method in interface NotFunctional.
Here’s an example that enumerates all the different Function variants, applied to lambda expressions:
// functional/FunctionVariants.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
import java.util.function.*;
class Foo {}
class Bar {
Foo f;
Bar(Foo f) {
this.f = f;
}
}
class IBaz {
int i;
IBaz(int i) {
this.i = i;
}
}
class LBaz {
long l;
LBaz(long l) {
this.l = l;
}
}
class DBaz {
double d;
DBaz(double d) {
this.d = d;
}
}
public class FunctionVariants {
static Function<Foo, Bar> f1 = f -> new Bar(f);
static IntFunction<IBaz> f2 = i -> new IBaz(i);
static LongFunction<LBaz> f3 = l -> new LBaz(l);
static DoubleFunction<DBaz> f4 = d -> new DBaz(d);
static ToIntFunction<IBaz> f5 = ib -> ib.i;
static ToLongFunction<LBaz> f6 = lb -> lb.l;
static ToDoubleFunction<DBaz> f7 = db -> db.d;
static IntToLongFunction f8 = i -> i;
static IntToDoubleFunction f9 = i -> i;
static LongToIntFunction f10 = l -> (int) l;
static LongToDoubleFunction f11 = l -> l;
static DoubleToIntFunction f12 = d -> (int) d;
static DoubleToLongFunction f13 = d -> (long) d;
public static void main(String[] args) {
System.out.println(f1 + ", " + f2 + ", " + f3 + ", " + f4 + ", " + f5);
Bar b = f1.apply(new Foo());
IBaz ib = f2.apply(11); // interface Function method
LBaz lb = f3.apply(11);
DBaz db = f4.apply(11);
int i = f5.applyAsInt(ib); // interface ToIntFunction method
long l = f6.applyAsLong(lb); // interface ToLongFunction method
double d = f7.applyAsDouble(db);// interface ToDoubleFunction method
System.out.println(i + ", " + l + ", " + d);
l = f8.applyAsLong(12);
d = f9.applyAsDouble(12);
i = f10.applyAsInt(12);
System.out.println(i + ", " + l + ", " + d);
d = f11.applyAsDouble(12);
i = f12.applyAsInt(13.0);
l = f13.applyAsLong(13.0);
System.out.println(i + ", " + l + ", " + d);
}
}
My Output:
FunctionVariants$$Lambda$1/135721597@6e8cf4c6, FunctionVariants$$Lambda$2/455659002@12edcd21, FunctionVariants$$Lambda$3/2003749087@34c45dca, FunctionVariants$$Lambda$4/18319
32724@52cc8049, FunctionVariants$$Lambda$5/1149319664@5b6f7412
11, 11, 11.0
12, 12, 12.0
13, 13, 12.0
references:
1. On Java 8 - Bruce Eckel
2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/functional/FunctionalAnnotation.java
3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/functional/FunctionVariants.java