最近我开始探索Java 8,我无法理解“功能接口”的概念,这对Java实现lambda表达式至关重要。在Java中有一个pretty comprehensive guide到lambda函数,但我被卡在the chapter that gives definition to the concept of functional interfaces上。定义如下:
更确切地说,功能接口被定义为具有一个抽象方法的任何接口。
然后他进入示例,其中一个是Comparator
接口:
public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
我能够测试我可以使用lambda函数代替Comparator参数并且它可以工作(即Collections.sort(list, (a, b) -> a-b)
)。
但是在Comparator界面中,compare
和equals
方法都是抽象的,这意味着它有两个抽象方法。那么如果定义要求接口具有恰好一个抽象方法,那么它如何工作?我在这里缺少什么?
答案 0 :(得分:55)
接口Comparator是有用的,因为虽然它声明了两个抽象方法,但其中一个 - equals-具有与Object中的公共方法相对应的签名。接口总是声明对应于Object的公共方法的抽象方法,但它们通常是隐式的。无论是隐式声明还是显式声明,此类方法都会从计数中排除。
我真的不能说得更好。
修改:根据Maurice的评论(感谢!)更新到此页面的最新文本
答案 1 :(得分:7)
另一种解释在@FunctionalInterface page:
中给出从概念上讲,功能界面只有一个抽象方法。由于默认方法具有实现,因此它们不是抽象的。 如果接口声明覆盖
java.lang.Object
的公共方法之一的抽象方法,那么也不会计入接口的抽象方法计数,因为接口的任何实现都将具有java.lang.Object
的实现或其他地方。
您可以使用 @FunctionalInterface
测试哪个界面是正确的功能界面。
E.g:
这项工作
@FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals(Object o);
}
这会产生错误:
@FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals();
}
在FunctionalInterf接口
中找到多个非重写抽象方法
答案 2 :(得分:3)
Q值。但是在Comparator接口中,compare()和equals()方法都是抽象的,这意味着它有两个抽象方法。那么如果定义要求接口只有一个抽象方法,那么它如何工作呢?我在这里缺少什么?
一个。
功能接口可以指定Object定义的任何公共方法,例如equals(), 而不影响其“功能接口”状态。公共Object方法被认为是隐式的 功能接口的成员,因为它们是由a的实例自动实现的 功能界面。
答案 3 :(得分:0)
Java文档说:
请注意,不要覆盖Object.equals(Object)总是安全的。 但是,在某些情况下,覆盖此方法可能会有所改善 通过允许程序确定两个不同的性能 比较器强制执行相同的命令。
也许Comparator很特别?也许,即使它是一个接口,也有某种调用equals()
的{{1}}默认实现?从算法上讲,它是微不足道的。
我认为在接口中声明的所有方法都是抽象的(即没有默认实现)。但也许我错过了一些东西。
答案 4 :(得分:0)
<强>定义:强>
如果一个接口只包含一个抽象方法,那么这种类型的接口称为功能接口。
<强>用法:强>
关于继承的功能界面:
如果接口扩展了Functional接口且子接口不包含任何抽象方法,则子接口也被视为功能接口。
功能界面对于java来说并不陌生,它已在以下接口API中使用:
答案 5 :(得分:0)
在Java 8之前,接口只能声明一个或多个方法,也称为抽象方法(没有实现的方法,只有签名)。从Java 8开始,接口还可以实现一个或多个方法(称为接口默认方法)和静态方法以及抽象方法的实现。界面默认方法标记为默认关键字。
问题是,什么是功能接口? 具有单一抽象方法(SAM)的接口称为功能接口。
意思是-
使用示例代码https://readtorakesh.blogspot.com/2018/08/functional-interface-java8.html
的更多详细信息答案 6 :(得分:0)
功能界面只有一种抽象方法,但可以具有多个默认和静态方法。
由于默认方法不是抽象的,因此您可以随意在功能接口中添加任意数量的默认方法。
@FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
default void perform1(){
//Method body
}
default void perform2(){
//Method body
}
}
如果接口声明的抽象方法覆盖java.lang.Object
的公共方法之一,则该方法也不计入接口的抽象方法计数,因为该接口的任何实现都将具有java.lang.Object
的实现或其他地方。
比较器是一个功能接口,即使它声明了两个抽象方法。因为这些抽象方法之一“ equals()
”的签名等于Object类中的公共方法。
例如界面下方是有效的功能界面。
@FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
@Override
public String toString(); //Overridden from Object class
@Override
public boolean equals(Object obj); //Overridden from Object class
}
答案 7 :(得分:0)
接口不能扩展对象类,因为接口必须有公共和抽象方法。
对于 Object 类中的每个公共方法,接口中都有一个隐式的公共和抽象方法。
这是标准的 Java 语言规范,声明如下,
<块引用>“如果一个接口没有直接的超接口,那么接口隐式声明一个公共抽象成员方法m,签名为s,返回类型r,并抛出子句t对应每个签名为s的公共实例方法m,返回类型为r , 和在 Object 中声明的 throws 子句 t ,除非接口显式声明了具有相同签名、相同返回类型和兼容的 throws 子句的方法。”
这就是在接口中声明 Object 类的方法的方式。根据 JLS,这不算作接口的抽象方法。因此,Comparator 接口是一个函数式接口。