我正在学习 Java 8 中的 lambda 表达式。有人可以向我解释如何将 lambda 表达式与只有一个方法的抽象类一起使用(如果可能的话)吗?
例如,这是抽象类:
public abstract class ClassA {
public abstract void action();
}
我还有另一个类在其构造函数中采用 ClassA
的实例:
public ClassB {
public ClassB(String text, ClassA a){
//Do stuff
}
}
所以我想知道如何写这样的东西:
ClassB b = new ClassB("Example", new ClassA(() -> System.out.println("Hello")));
显然该语句不起作用,但是有没有办法在这里使用 lambda 表达式?如果有,我做错了什么?
不,您无法实现此目的,因为ClassA
必须是一个函数式接口(interface)。函数式接口(interface)是只包含一个抽象方法的接口(interface)。除了抽象方法之外,它还可能包含零个或多个默认方法和/或静态方法。因为函数式接口(interface)只包含一个抽象方法,所以在使用 lambda 表达式实现它时可以省略该方法的名称。例如,考虑以下接口(interface):
interface Predicate<T> {
boolean test(T t);
}
此接口(interface)的目的是提供一种方法,该方法对类 T
的对象进行操作并返回一个 boolean
。您可以有一个方法,该方法采用实现此接口(interface)的类的实例,定义如下:
public void printImportantData(ArrayList<Data> dataList, Predicate<Data> p) {
for (Data d : dataList) {
if (p.test(d)) {
System.out.println(d);
}
}
}
Data
类可以像这样简单:
public class Data {
public int value;
}
现在,您可以按如下方式调用上述方法:
printImportantData(al, (Data d) -> { return d.value > 1; });
注意这里的方法没有名字。这是可能的,因为接口(interface)只有一个抽象方法,因此编译器可以找出名称。这可以缩短为:
printImportantData(al, (Data d) -> d.value > 1);
请注意,这里没有花括号,也没有 return 关键字。这是可能的,因为该方法返回一个 boolean 值并且表达式 d.value > 1
也返回一个 boolean 值。因此,编译器能够确定该表达式的值将从该方法返回。这可以进一步缩短为:
printImportantData(al, d -> d.value > 1);
注意 d
没有类型声明!编译器可以计算出它需要的所有信息,因为接口(interface)只有一个抽象方法,而该方法只有一个参数。因此,您无需在代码中编写所有这些内容。
将上述方法与旧的 Java 7 风格进行比较,使用一个内部类来有效地做同样的事情:
printImportantData(al, new Predicate<Data>() {
public boolean test(Data d) {
return d.value > 1;
}
});