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 {
// 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 {
int compare(T o1, T o2);
}
以下代码使用抽象通用方法定义非通用函数式接口:@FunctionalInterface
public interface Processor {
void process(T[] list);
}
Java Buildin函数式接口
Java 8在包java.util.function中有函数式接口
函数表示接受类型T的参数并返回类型R的结果的函数。
public interface Function{
...
public R apply(T t);
...
}
BiFunction
表示一个函数,它接受类型T和U的两个参数,并返回类型R的结果。public interface BiFunction{
...
public R apply(T t, U u);
...
}
谓词
表示为指定参数返回true或false的布尔函数。public Predicate {
...
public boolean test(T t);
...
}
BiPredicate
表示为两个指定的参数返回true或false的布尔函数。public interface BiPredicate{
...
public boolean test(T t, U u);
...
}
Consumer
表示接受参数并且不返回结果的操作。public interface Consumer{
...
public void accept(T t);
...
}
BiConsumer
表示接受两个参数并且不返回结果的操作。public interface BiConsumer{
...
public void accept(T t, U u);
...
}
Supplier
表示返回类型T的值的函数。public interface Supplier{
...
public T get();
...
}
UnaryOperator
表示接受参数并返回相同类型的结果的函数。public interface UnaryOperator{
...
public T apply(T t);
...
}
BinaryOperator
表示一个函数,它接受两个参数并返回相同类型的结果。public interface BinaryOperator{
...
public T apply(T t1, T t2);
...
}
注意2
上述通用buildin函数式接口都是更专用的函数式接口的通用版本。
例如,IntConsumer是Consumer的专用版本。