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

2022-09-04 19:31:29

我正在学习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表达式?如果有,我做错了什么?


答案 1

不,您无法实现此目的,因为必须是功能接口。功能接口是只包含一个抽象方法的接口。除了抽象方法之外,它还可以包含零个或多个默认方法和/或静态方法。由于函数接口只包含一个抽象方法,因此在使用 lambda 表达式实现该方法时,可以省略该方法的名称。例如,请考虑以下接口:ClassA

interface Predicate<T> {
    boolean test(T t);
}

此接口的目的是提供一个方法,该方法对类的对象进行操作并返回 .你可以有一个方法,它采用一个类的实例,该实例实现如下定义的接口:Tboolean

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; }); 

请注意,该方法在此处没有名称。这是可能的,因为接口只有一个抽象方法,因此编译器可以找出名称。这可以缩短为:

printImportantData(al, (Data d) -> d.value > 1);

请注意,此处没有大括号,也没有返回关键字。这是可能的,因为该方法返回一个布尔值,并且表达式也返回一个布尔值。因此,编译器能够确定此表达式的值是从该方法返回的。这可以进一步缩短为:d.value > 1

printImportantData(al, d -> d.value > 1);

请注意,没有 的类型声明 !编译器可以找出所需的所有信息,因为接口只有一个抽象方法,而该方法只有一个参数。因此,您不需要在代码中编写所有这些内容。
将上述方法与旧的Java 7样式进行比较,使用内部类有效地执行相同的操作:d

printImportantData(al, new Predicate<Data>() {
    public boolean test(Data d) {
        return d.value > 1;
    }
});

答案 2

您只能使用 lambda 表达式实例化功能接口。

例如:

如果您更改为接口(您可能希望重命名它):ClassA

public interface ClassA {
    public abstract void action();
}

并保持原样:ClassB

public class ClassB {
   public ClassB(String text, ClassA a){
      //Do stuff
    }
}

您可以使用以下命令将(接口)的实例传递给构造函数:ClassAClassB

ClassB b = new ClassB("Example", () -> System.out.println("Hello"));    

另一方面,您的

ClassB b = new ClassB("Example", new ClassA(() -> System.out.println("Hello")));

尝试失败的原因有以下几个:

  1. 不能实例化抽象类(只能实例化该类的子类)。
  2. 即使你可以实例化类(如果它不是抽象的),你也没有构造函数将某些函数接口作为参数,所以你不能作为参数传递给 的构造函数。ClassAClassA() -> System.out.println("Hello")ClassA

推荐