Java 8 - 函数式接口 vs 抽象类

7

我正在探索Java 8的功能,发现了"函数接口"

据我了解,这些接口可以具有一些默认实现方法:

@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface 
{
    default public void doSomeWork()
    {
        System.out.println("Doing some work in interface impl...");
    }
    default public void doSomeOtherWork()
    {
        System.out.println("Doing some other work in interface impl...");
    }
}

但我怀疑这抽象类的作用是什么。

为什么要引入函数式接口

5个回答

15

但是我有疑问,这就是抽象类的用途。

为什么要引入函数式接口。

可以扩展的类的数量:1

可以实现的接口数量:多于1个


这是唯一的原因吗?在jdk1.7之前,Java非常提供不支持多重继承。 - codingenious
你仍然没有多重继承。 你只能从一个源继承,但是你可以实现多个接口 - 与之前相同。 继承图仍然是一个有向无环图。 - Markus Koivisto
但是,通过实现多个功能接口,不会出现钻石问题吗? - codingenious
@Batty 显然,钻石问题只会在函数接口中提供默认函数实现时出现(这也是一个新事物) - 编译器通过强制实现类提供这些方法的实现来解决当多个默认实现在接口中被发现时的问题。 - demaniak

3

功能接口被用于“安全”的多重继承。区别如下:

  • 一个类可以扩展多个功能接口
  • 功能接口只能有一个抽象方法
  • 与C++抽象类不同,功能接口不能有字段

典型用法是当您想要将默认功能嵌入对象中时。即如果您有一个类似函数的对象,

class MyFunction1 {
    public Integer apply(String s){
        ...
    }
}

class MyFunction2 {
    public List<String> apply(Integer s){
        ...
    }
}

如果你想从它们中制作一个组合,只需加入 implements Function:
class MyFunction1 implements Function<String, Integer>{
    public Integer apply(String s){
        ...
    }
}

class MyFunction2 implements Function<Integer, List<String>>{
    public List<String> apply(Integer s){
        ...
    }
}

你可以创建一个由函数组成的组合体。比较两种方法: 没有功能接口:
MyFunction1 myFunction1 = ...;
MyFunction2 myFunction2 = ...;

Function<String, List<String>> composition = (s) -> myFunction2.apply(myFunction1.apply(s));

带有功能接口:
MyFunction1 myFunction1 = ...;
MyFunction2 myFunction2 = ...;

Function<String, List<String>> composition = myFunction1.andThen(myFunction2);
区别:
  • 无需重新实现 函数。
  • 在扩展类中可用的其他函数composeidentity
  • 新的默认函数是类层次结构的一部分无需创建新对象。通常像 compose() 这样的函数不会被包含在类定义中,因为这会导致类大小增加。它们通常被放置在单独的实用程序类中。在 Guava 中,组合被放置在一个单独的实用程序类 Functions 中:Functions.compose。因此,使用新的函数接口时,您不需要记住您的函数实现在哪个实用程序类中。

如果两个接口都有一个名为“public Integer apply(String s)”的方法,这不会成为问题吗? - codingenious
如果功能接口具有相同的抽象方法签名,这将导致编译时错误。我理解这就是方法内联 - 在类中不能有重复的方法。 - Andrey Chaschev

1

0

我还没有使用过JAVA 8,但从我所看到的来看,它可以允许一种多重继承,这是使用抽象类不可能实现的。


这仍然不是多重继承。 - Markus Koivisto
@MarkusKoivisto:为什么不呢?你可以有带有主体的变量和方法。你说缺少了什么,这就不是多重继承了吗? - codepleb

0

接口Comparator是函数式的,尽管它明确声明了两个方法,但只有一个是抽象的;equals是从Object继承的具体方法的显式声明,如果没有这个声明,否则将隐式声明。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接