@FunctionalInterfaces可以有默认方法吗?

时间:2015-05-11 10:15:57

标签: java java-8

为什么我无法使用默认方法实现创建@FunctionalInterface

@FunctionalInterface
public MyInterface {
    default boolean authorize(String value) {
        return true;
    }
}

5 个答案:

答案 0 :(得分:40)

您可以在functional interface中使用默认方法,但其合同要求您提供一种抽象方法(或SAM)。由于默认方法有实现,因此它不是抽象的。

  

从概念上讲,功能界面只有一个抽象方法。   由于默认方法具有实现,因此它们不是抽象的。

  

如果使用此注释类型注释类型,则编译器是   需要生成错误消息,除非:

     

类型是接口类型,而不是注释类型,枚举或   类。

     

带注释的类型满足功能的要求   接口

在这里,您不能满足功能界面的要求,因此您需要提供一种抽象方法。例如:

@FunctionalInterface
interface MyInterface {

    boolean authorize(int val);

    default boolean authorize(String value) {
        return true;
    }
}

请注意,如果您声明一个抽象方法覆盖Object类中的一个公共方法,那么它不会计数,因为此接口的任何实现都将至少通过这些方法实现这些方法对象的类。例如:

@FunctionalInterface
interface MyInterface {

    default boolean authorize(String value) {
        return true;
    }

    boolean equals(Object o);
}

无法编译。

答案 1 :(得分:12)

功能界面是具有单个抽象方法的interface。定义功能接口的整个目的是通过lambda表达式实现单个抽象方法,这将有效地覆盖该方法,这使得为它提供default实现毫无意义。

完全由interface方法组成的default会引发多个问题。存在技术问题,当存在多个default方法时,编译器无法决定实现哪种方法的lambda表达式,并且存在interface完全由{{1}组成的语义问题}方法不是default。您无法实例化此默认行为,因为您无法实例化abstract并且正在强制程序员创建具体类只是为了调用默认行为,因为接口是无状态的,可以由单例提供:

interface

请注意,如果需要,您可以使用扩展功能接口的接口并提供默认方法。但是,如果这导致创建一个没有抽象方法的@FunctionalInterface public interface MyInterface { static MyInterface DEFAULT = s->true; boolean authorize(String value); } ,我会质疑设计。您可以与discussion about marker interfaces with default methods进行比较。如果子接口将具有与功能接口不同的抽象方法,那么它就是一个不同的故事。可能存在实际用例,但这些子接口还将说明为什么它们不应与函数库interface混合,因为lambda表达式将始终实现 abstract 方法

答案 2 :(得分:5)

那是因为@FunctionalInterface可以拥有默认方法,可以根据需要使用。例如,考虑java.util.Function接口。它包含两个默认方法:composeandThen。但是应该只有一个非默认方法。否则编译器如何知道哪些默认方法应该映射到lambda?

答案 3 :(得分:0)

具有一种抽象方法的接口,称为功能接口或单一抽象方法接口(SAM接口)。

  • 只需要一种抽象方法
  • @FunctionalInterface注释可以添加
  • 默认方法不是抽象的,因此我们可以添加任意数量的默认方法
  • 允许将Object类的方法重写为抽象的
  • 功能性(SAM)接口对于编写lambda表达式非常重要
  • 在Java 8中的java.util.function包下添加了许多功能(SAM)接口

您可以在What is SAM interface?

阅读更多内容

答案 4 :(得分:-1)

我只想再增加几分。

  1. 我们在FuntionalInterface中可以使用任意数量的 Abstract 方法。

  2. 我们还可以在FuntionalInterface中使用任意数量的 Static 方法。

  3. 我们还可以声明一个抽象方法,该抽象方法重写Object类中的一个公共方法,但是此功能接口中也必须有其他自定义抽象方法,如下面的代码所示

    @FunctionalInterface 公共接口SAM { 公共无效helloSam();

        default void xyz() {
            System.out.println("xyz");
        }
    
        static void abc() {
            System.out.println("abc");
        }
    
        static void abc1() {
            System.out.println("abc1");
        }
    
        default void xyz1() {
            System.out.println("xyz1");
        }
    
         boolean equals(Object o);
    }