java8函数式接口@FunctionalInterface

TOC

函数式接口@FunctionalInterface

研究之前最好学习一下Lambda 表达式

参考

函数式接口概述

所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces

在 Java 中,Marker(标记)类型的接口是一种没有方法或属性声明的接口,简单地说,marker 接口是空接口。相似地,函数式接口是只包含一个抽象方法声明的接口

java.lang.Runnable 就是一种函数式接口,在 Runnable 接口中只声明了一个方法 void run(),相似地,ActionListener 接口也是一种函数式接口,我们使用匿名内部类来实例化函数式接口的对象,有了 Lambda 表达式,这一方式可以得到简化。

每个 Lambda 表达式都能隐式地赋值给函数式接口,例如,我们可以通过 Lambda 表达式创建 Runnable 接口的引用。

Runnable r = () -> System.out.println("hello world");

当不指明函数式接口时,编译器会自动解释这种转化:

new Thread(
   () -> System.out.println("hello world")
).start();

因此,在上面的代码中,编译器会自动推断:根据线程类的构造函数签名 public Thread(Runnable r) { },将该 Lambda 表达式赋给 Runnable 接口。

以下是一些 Lambda 表达式及其函数式接口:

Consumer<Integer>  c = (int x) -> { System.out.println(x) };
BiConsumer<Integer, String> b = (Integer x, String y) -> System.out.println(x + " : " + y);
Predicate<String> p = (String s) -> { s == null };

@FunctionalInterface是 Java 8 新加入的一种接口,用于指明该接口类型声明是根据 Java 语言规范定义的函数式接口。Java 8 还声明了一些 Lambda 表达式可以使用的函数式接口,当你注释的接口不是有效的函数式接口时,可以使用 @FunctionalInterface解决编译层面的错误。

特点

  • 接口有且仅有一个抽象方法(abstract)
  • 允许定义静态方法static
  • 允许定义默认方法default
  • 允许java.lang.Object中的public方法
  • 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

    符合函数式接口的,可以不加这个注解,不是函数式接口的加了注解会报错(建议加上,否则被别人改了还不报错就坏了)

定义

比如可以这样定义

@FunctionalInterface
public interface WorkerInterface { 
    //抽象关键字可以省略
    public void doSomeWork();
    //public void doSomeMoreWork();//根据定义,函数式接口只能有一个抽象方法,如果你尝试添加第二个抽象方法,将抛出编译时错误。
}
//若是加上第二个抽象方法会报错
Unexpected @FunctionalInterface annotation
    @FunctionalInterface ^ WorkerInterface is not a functional interface multiple
    non-overriding abstract methods found in interface WorkerInterface 1 error

也可以

// 正确的函数式接口
@FunctionalInterface
public interface TestInterface {

    // 抽象方法
    public void sub();

    // java.lang.Object中的public方法,可以留着
    public boolean equals(Object var1);

    // 默认方法 default可以
    public default void defaultMethod(){

    }

    // 静态方法 static方法可以
    public static void staticMethod(){

    }
}

// 错误的函数式接口(有多个抽象方法)
@FunctionalInterface
public interface TestInterface2 {

    void add();

    void sub();
}

使用

  • 案例1
//定义一个函数式接口
@FunctionalInterface
public interface WorkerInterface {
    public void doSomeWork();
}
public class WorkerInterfaceTest {
    public static void execute(WorkerInterface worker) {
        //传入实现的函数式接口类,调用接口方法
        worker.doSomeWork();
    }
    public static void main(String[] args) {
        //普通调用方法
        execute(new WorkerInterface() {
            //调用WorkerInterface,实现接口
            @Override
            public void doSomeWork() {
                System.out.println("Worker invoked using Anonymous class");
            }
        });
        //Lambda 优化
        execute(() -> System.out.println("Worker invoked using Lambda expression"));
    }
}
/////////
输出:
Worker invoked using Anonymous class
Worker invoked using Lambda expression




原文地址:https://www.cnblogs.com/ziyue7575/p/c3a8359c44b7e519f12eb004d33f4b44.html