Java Lambda – Java函数式接口
函数式接口是具有一个方法的接口,用作lambda表达式的类型。
public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent event); }
ActionListener
只有一个方法actionPerformed
。它是一个函数式接口。无论调用什么单一方法,只要Java编译器具有兼容的方法签名,Java编译器就会将其匹配到您的lambda表达式。
lambda表达式表示函数式接口的实例。
lambda表达式的类型是一个函数式接口类型。
(String str) -> str.length()
str.length() 获取一个String参数并返回其长度。
它的类型可以是任何具有抽象方法的函数接口类型,它使用String作为参数并返回int。
以下是这种函数式接口的示例:
@FunctionalInterface interface Processor { int getStringLength(String str); }
我们可以为其函数式接口实例赋值lambda表达式。
Processor stringProcessor = (String str) -> str.length();
例子
在下面的代码中,我们为其函数接口赋值一个lambda表达式。然后我们通过调用函数接口中定义的方法来执行lambda表达式,并传入一个参数。
public class Main { public static void main(String[] argv) { Processor stringProcessor = (String str) -> str.length(); String name = "Java Lambda"; int length = stringProcessor.getStringLength(name); System.out.println(length); } } @FunctionalInterface interface Processor { int getStringLength(String str); }
上面的代码生成以下结果。
注意
lambda表达式本身不能用作独立的表达式。
lambda表达式的类型由编译器推断。
Java函数式接口定义
函数式接口是具有一个抽象方法的接口。
我们不能使用以下类型的方法来声明一个函数式接口:
- 默认方法
- 静态方法
- 从Object类继承的方法
一个函数式接口可以重新声明Object类中的方法。该方法不被视为抽象方法。因此,我们可以声明lambda表达式使用的另一种方法。
考虑 java.util
包中的Comparator类,如下所示:
package java.util; @FunctionalInterface public interface Comparator<T> { // An abstract method declared in the functional interface int compare(T o1, T o2); // Re-declaration of the equals() method in the Object class boolean equals(Object obj); ... }
Comparator接口有两个抽象方法: compare()
和 equals()
。
equals()
方法是Object类中的 equals()
方法的重新声明。
@FunctionalInterface注释
@FunctionalInterface
注释在java.lang包中定义。我们可以选择使用它来标记一个函数式接口。
如果注释 @FunctionalInterface
在非函数式接口或其他类型(如类)上注释,则会发生编译时错误。
具有一个抽象方法的接口仍然是一个功能接口,即使我们不用 @FunctionalInterface
注释。
public class Main { public static void main(String[] argv) { Processor stringProcessor = (String str) -> str.length(); String name = "Java Lambda"; int length = stringProcessor.getStringLength(name); System.out.println(length); } } @FunctionalInterface interface Processor { int getStringLength(String str); }
上面的代码生成以下结果。
通用函数式接口
我们可以使用类型参数与函数式接口来创建通用函数式接口。
以下代码创建具有一个类型参数T的通用函数式参数函数接口。
@FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); }
以下代码使用抽象通用方法定义非通用函数式接口:
@FunctionalInterface public interface Processor { <T> void process(T[] list); }
Java Buildin函数式接口
Java 8在包java.util.function中有函数式接口
函数
表示接受类型
T
的参数并返回类型
R
的结果的函数。
public interface Function<T,R>{ ... public R apply(T t); ... }
BiFunction
表示一个函数,它接受类型T和U的两个参数,并返回类型R的结果。
public interface BiFunction<T,U,R>{ ... public R apply(T t, U u); ... }
谓词
表示为指定参数返回 true
或 false
的布尔函数。
public Predicate<T> { ... public boolean test(T t); ... }
BiPredicate
表示为两个指定的参数返回 true
或 false
的布尔函数。
public interface BiPredicate<T,U>{ ... public boolean test(T t, U u); ... }
Consumer
表示接受参数并且不返回结果的操作。
public interface Consumer<T>{ ... public void accept(T t); ... }
BiConsumer
表示接受两个参数并且不返回结果的操作。
public interface BiConsumer<T,U>{ ... public void accept(T t, U u); ... }
Supplier
表示返回类型T的值的函数。
public interface Supplier<T>{ ... public T get(); ... }
UnaryOperator
表示接受参数并返回相同类型的结果的函数。
public interface UnaryOperator<T>{ ... public T apply(T t); ... }
BinaryOperator
表示一个函数,它接受两个参数并返回相同类型的结果。
public interface BinaryOperator<T>{ ... public T apply(T t1, T t2); ... }
注意2
上述通用buildin函数式接口都是更专用的函数式接口的通用版本。
例如, IntConsumer
是 Consumer<T>
的专用版本。