功能接口的概念

Concept of functional interface

当我浏览 lambda 表达式时,这本书触及了一个只有一个抽象方法的 函数式接口。我的问题解决了那个测验问题

/* Which of these interfaces are functional interfaces? */
public interface Adder{
   int add(int a, int b);
}
public interface SmartAdder extends Adder{
   int add(double a, double b);
}
public interface Nothing{
}

我知道最后一个不是,但是我觉得第一个和第二个应该是函数式接口。但是书上说第二个不是。为什么?它不会覆盖 add 方法吗?那么即使是秒,抽象方法不也只有一个吗?

SmartAdder 有两种方法。方法签名不同。功能接口只能有一个方法。

找出答案的一个简单方法是尝试定义一个实现 SmartAdder 的 class。编译器会告诉你需要同时实现 add(int, int)add(double, double).

您认为 add(double, double) 会覆盖 add(int, int) 是可以理解的,但它们实际上是不同的方法,并且可能具有完全不相关的实现。

如果 SmartAdder 定义了 add(int, int)default 实现,它 仍将是 函数接口:

public interface SmartAdder extends Adder {
   int add(double a, double b);

   default int add(int a, int b) {
     return add((double)a, (double)b); // this calls the double method instead
  }
}

您可能还遇到过 @FunctionalInterface 注释 - 这可以放在接口上以在编译时强制接口只有一个抽象方法。如果 SmartAdder 被注释为 @FunctionalInterface 接口本身将无法编译。

interface SmartAdder 超载,而不是覆盖 interface Adder。那是因为名字是同一个名字,只是参数类型不同。因此,它有2个功能。要成为一个函数式界面,它只需要有一个函数。

==> 只有interface Adder是函数式接口。

在 Java 中,子类型 中的方法覆盖 具有相同 签名 的父类型的方法.签名意味着方法的名称和参数。特别是,参数必须是完全相同的类型,并且必须在两个方法中以完全相同的顺序声明,即子类型中声明的方法的参数类型不能是子类型或比方法类型更宽的类型在父类型的方法中声明的参数。

因此,在您的 SmartAdder 接口中,带有签名 add(double a, double b) 的方法不会覆盖 Adder 接口的方法 add(int a, int b),因为 doubleint 宽。当一个类型有两个或多个同名但参数不同的方法时,它被称为方法重载,它与方法覆盖完全不同。

这就是为什么 SmartAdder 最终有两个抽象方法,因此它不是函数式接口(它要求类型只有一个抽象方法)。