【Java8】函数式接口及Lamda表达式详解

函数式接口基本介绍

1、函数式接口:只有一个方法的接口;
2、有且仅有一个抽象方法的接口,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda就是Java中函数式编程的体现;
3、主要分布在 java.util.function 包下,常见的 4大原始函数 接口为:Function (函数型接口)、Predicate (断定型接口)、Consumer (消费型接口)、Supplier (供给型接口)

使用场景

1、在函数式编程场景中进行使用,Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口;
2、函数作为参数,匿名内部类替代,可以简化代码,提高编码效率;
3、延迟加载,即满足条件才会执行,不满足条件就不执行。

@FunctionalInterface注解

1、 Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解放在接口上,表示此接口是一个函数式接口。并且提示编译器去检查接口是否仅包含一个抽象方法,即,是否符合函数式编程的定义;
2、 注意:如果自定义一个符合规范的函数式接口,也可以不加@FunctionalInterface注解,此注解只是起到一个提示编译器进行规范检查的作用;
3、 日常开发中用的最多的函数式接口的,比如线程中的 Runnable

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

常见函数式接口使用

1、Function (函数型接口),有一个输入参数,有一个输出,apply ()方法就是该接口的唯一方法,也就是继承该Function接口,唯一需要实现的方法,代码示例:

// 输出输入的参数:有一个输入参数,和一个输出
public static void main(String[] args) {
  // 1. 初始化,并且实现该接口的唯一实现方法
  Function<String,String> function = new Function<String, String>() {
    @Override
    public String apply(String param) {
        return param;
    }
  };
  System.out.println(function.apply("abc"));
}

Lambda就是Java中函数式编程的体现 也就是说只要是函数式接口,就可以使用lambda表达式来简化代码!如下:

public static void main(String[] args) {
     // 使用lambda表达式
     Function<String,String> function = (str)->{return str;};
     //或者我们可以更简单点,把str的()括号去掉也是可以的
    // Function<String,String> function = str->{return str;};
     System.out.println(function.apply("abc"));
}

典型的lambda表达式语法:()->{};str是传入的参数
2、Predicate (断定型接口),有一个输入参数,返回值只能是布尔值,代码示例:

Predicate<Integer> predicate = integer -> {
        if(integer > 0){
        return true;
        }
        return false;
        };
        predicate.test(3);

3、 Consumer (消费型接口),只有入参,没有返回值

Consumer<String> consumer = str-> System.out.println(str);
consumer.accept("abc");

4、Supplier (供给型接口),没有参数,只有返回值

Supplier<Integer> supplier = ()-> 1024;
System.out.println(supplier.get());

Lambda表达式及匿名内部类
1、Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁;
2、lambda表达式,其实本质来讲,就是⼀个匿名函数。因此在写lambda表达式的时候,不需要关心方法名是什么。实际上,我们在写lambda表达式的时候,也不需要关心返回值类型;
3、Lambda使用代码示例:

// 1、匿名内部类没有类名,只被使用一次,使代码更简洁;
// 2、在定义之后就可以立即使用,定义时就实例化
// 3、方便编写事件驱动程序及线程代码
public class LambdaUse {
    // 匿名内部类
    public void anonymousInner(String hello){
        HelloFunction helloFunction = new HelloFunction(){
            @Override
            public void sayHello(String hello){
                System.out.println(hello);
            }
        };
        helloFunction.sayHello(hello);
    }
    // 局部类
    public void implementsClass(){
        class Hello implements HelloFunction{
            @Override
            public void sayHello(String hello) {
                System.out.println("扩展类:"+hello);
            }
        }
        Hello hello = new Hello();
        hello.sayHello("匿名内部类");
    }
    // lambda表达式
    public void lambda(String hello){
        HelloFunction helloFunction = System.out::println;
        helloFunction.sayHello(hello);
    }

    public static void main(String[] args) {
        LambdaUse lambdaUse = new LambdaUse();
        lambdaUse.lambda("你好匿名内部类。");
        lambdaUse.implementsClass();
    }
    // 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
    // Lambda表达式:只可能是接口,如果接口中仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名表达式,
    // 如果接口中有多个抽象,只能使用匿名内部类
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容