具有只有一种方法的抽象类的 Java 8 lambda 表达式

标签 java lambda java-8

<分区>

我正在学习 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;
    }
});

关于具有只有一种方法的抽象类的 Java 8 lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47874325/

相关文章:

java - AOP编程——ProceedingJoinPoint只支持around advice

java - 如何使用 Java comm API 处理读取超时

Python 闭包和单元格(闭包值)

java - 使用 Streams 将 BigDecimals 相加

java - ThrowableCaptor 可在 Eclipse 中运行,但不能在 Netbeans 中运行

java - 如何使用 LambdaMetaFactory 实例化对象?

java - Java 中的 getter 和 setter

java - 如何检查用户是否单击了 JPanel 中的任何按钮

python - 根据其他列的条件在 Pandas 中创建一个新列

c# - 如何在Linq语句中转换并赋值正确