当我瞥一眼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
方法吗?所以即使在第二种情况下,是不是只有一种抽象方法?
答案 0 :(得分:4)
一种简单的方法是尝试定义一个实现SmartAdder
的类。编译器会告诉您需要实现add(int, int)
和add(double, double)
。
您认为add(double, double)
会覆盖add(int, int)
这是可以理解的,但它们实际上是单独的方法,并且可能具有完全不相关的实现。
如果SmartAdder
已定义default
add(int, int)
的{{1}}实现,那么 仍将是功能界面:
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
进行注释,则接口本身将无法编译。
答案 1 :(得分:1)
SmartAdder有两种方法。方法签名是不同的。功能界面只能有一种方法。
答案 2 :(得分:1)
interface SmartAdder
重载,而不是覆盖interface Adder
。这是因为名称相同,但参数类型不同。因此,它有2个功能。要成为功能接口,它只需要一个功能。
==>只有interface Adder
是一个功能界面。
答案 3 :(得分:1)
在Java中,当子类型具有相同的签名时,子类型中的方法会覆盖父类型的方法。签名表示方法的名称和参数。特别是,参数必须具有相同的确切类型,并且必须在两种方法中以相同的顺序声明,即子类型中声明的方法的参数类型不能是子类型或类型更广泛的类型。在父类型的方法中声明的参数。
因此,在您的SmartAdder
界面中,带有签名add(double a, double b)
的方法不会覆盖add(int a, int b)
界面的方法Adder
,因为double
更宽比int
。当一个类型有两个或多个具有相同名称但具有不同参数的方法时,它被称为方法重载,它与方法重写完全不同。
这就是SmartAdder
最终有两个抽象方法的原因,因此它不是一个功能接口(它要求类型只有一个抽象方法)。