随着Java 8发布,函数式接口成为了一个热门话题。那么,我们首先需要了解什么是函数式接口。
函数式接口是指只有一个抽象方法的接口。简单来说,就是只有一个待实现方法的接口。这种接口是函数式接口,用于定义Lambda表达式的类型。Java 8中为了让Lambda表达式得到更好的支持,增加了很多函数式接口。
在Java 7以前,为了实现回调函数,我们需要定义一个接口,并在使用时进行实现。而引入Lambda表达式之后,我们可以直接将一个Lambda表达式传递给一个方法,使得代码更加简洁易懂。Lambda表达式可以说是Java 8的一个重要特性,但是Lambda表达式无法直接传递给方法,Lambda表达式的类型是一个函数式接口类型。
下面我们来看一个基础用法:
@FunctionalInterface
interface MyFunction {
void print(String message);
}
上面定义的MyFunction
接口只有一个抽象方法,它被Java 8标记为了一个函数式接口。接下来我们就可以使用上面的接口定义一个Lambda表达式了:
public static void main(String[] args) {
MyFunction myFunction = (message) -> System.out.println(message);
myFunction.print("Hello Java 8!");
}
代码输出:
Hello Java 8!
除了Java 8标准库中常用的函数式接口Supplier
、Consumer
、Function
、Predicate
之外,Java 8还新增了很多函数式接口。
BiConsumer
接口代表了一个接受两个输入的操作,并不返回任何结果的方法。
@FunctionalInterface
interface BiConsumer<T, U> {
void accept(T t, U u);
}
举个例子:
public static void main(String[] args) {
BiConsumer<String, Integer> print = (message, count) -> {
for (int i = 0; i < count; i++) {
System.out.println(message);
}
};
print.accept("Hello Java 8!", 3);
}
代码输出:
Hello Java 8!
Hello Java 8!
Hello Java 8!
BiFunction
接口代表了一个接受两个输入参数并返回一个结果的方法。
@FunctionalInterface
interface BiFunction<T, U, R> {
R apply(T t, U u);
}
下面是一个求两个数之和的例子:
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(1, 2)); //输出3
}
BinaryOperator
接口代表了一个二元操作,在把它应用于两个操作数时,产生了一个相同类型的结果。
@FunctionalInterface
interface BinaryOperator<T> extends BiFunction<T, T, T> {
//省略定义
}
下面是一个用BinaryOperator
计算斐波那契( Fibonacci )数列的例子:
public static void main(String[] args) {
BinaryOperator<Integer> fibonacci = (n, m) -> {
int []fib = {0, 1};
for (int i = 2; i <= n; i++) {
int fibn = fib[0] + fib[1];
fib[0] = fib[1];
fib[1] = fibn;
}
return fib[1];
};
System.out.println(fibonacci.apply(10, 0)); //输出55
}
Java 8中引入了函数式接口,为Lambda表达式的使用提供了更好的支持。值得注意的是,定义一个函数式接口时,我们需要在它的方法前标记上@FunctionalInterface
注解,这样当它不是函数式接口时,编译器会报错。该特性使得Java 8的代码更加简洁易懂,并提高了代码的可读性和可维护性。