java的lambda表达式

霸气de小男生 提交于 2020-01-20 20:35:02

lambda表达式的格式

以->分隔,前边是参数列表,后边是表达式体也就是具体要执行得到逻辑。
根据参数列表的个数有无返回值等可以分为6种形式,这个不必多说。

lambda表达式依赖函数式接口

lambda表达式依赖于函数式接口,即只有一个抽象方法的接口。个人理解表达式体就是实现那个唯一抽象方法的。也就是创建了一个实现这个接口的一个对象。需要注意的是,若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明,也就是lambda表达式里不能抛出异常,或者try/catch。
我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。
在这里插入图片描述

Java内置的四大函数式接口

在这里插入图片描述

@Test
    public void test6() {
        Supplier<String> supplier = ()->"532323".substring(0, 2);
        System.out.println(supplier.get());
    }
    @Test
    public void test7() {
        Function<String, String> function = (x)->x.substring(0, 2);
        System.out.println(function.apply("我是中国人"));
    }
    @Test
    public void test8() {
        Predicate<String> predicate = (x)->x.length()>5;
        System.out.println(predicate.test("12345678"));
        System.out.println(predicate.test("123"));
    }

运行结果:
在这里插入图片描述

方法引用

还有更简洁的方式。
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
方法引用就是Lambda表达式,就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
要求:实现抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
方法引用:使用操作符 “::” 将类(或对象) 与 方法名分隔开来。
如下三种主要使用情况:
对象::实例方法名
类::静态方法名
类::实例方法名
“实现抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致” 这句话很重要,一定要理解
我的理解是:
举个例子
Comparator comparator = (x,y)->Integer.compare(x, y);等同于
Comparator comparator1 = Integer::compare;
即:方法引用的方法是Integer的compare吧,他的参数列表是两个integer类型,返回值是int,这个例子中的抽象方法是Comparator接口的compare()方法
在这里插入图片描述

 public void test12() {
        Comparator<Integer> comparator = (x,y)->Integer.compare(x, y);
        Comparator<Integer> comparator1 = Integer::compare;
        int compare = comparator.compare(1, 2);
        int compare2 = comparator1.compare(1, 2);
        System.out.println("compare:"+compare);
        System.out.println("compare2:"+compare2);

    }

运行结果:

compare:-1
compare2:-1

还有构造方法引用
构造方法引用的语法是:类名::new

关于lambda表达式里不能抛出受查异常问题

首先,运行时异常可以抛出,因为运行时异常编译器不管,只有在程序运行时发生后直接挂掉程序就行。但是受查异常编译器要求必须处理,否则编译不通过,要么try/catch掉要么向上抛让,但是lambda里不能向上抛,原因是lambda表达式本质是执行了函数式接口里的那个唯一抽象方法,如果这个方法抛异常那么这个接口也要抛异常,但是这个接口源码是不能改的,也就是不能抛出去异常。如果你自己定义的函数接口那个抽象方法抛出了异常,那么lambda表达式就可以抛异常。

自己写的例子

package com.company.java8.lambda;
@FunctionalInterface
public interface ConsumerInterface <T>{
    void accept(T t);
}

package com.company.java8.lambda;


import java.util.List;

public class TestStream<T> {
    private List<T> list;
    public void myForEach(ConsumerInterface<T> sonsumer){
        for(T t:list){
            sonsumer.accept(t);
        }
    }
    public void setList(List<T> list){
        this.list=list;
    }
}

package com.company.java8.lambda;

import java.util.Arrays;
import java.util.List;

public class Test {
    public static void main(String[] args){
        TestStream<String> stream = new TestStream<String>();
        List list = Arrays.asList("11","22","33");
        stream.setList(list);
        stream.myForEach(str -> {System.out.println(str);
           // 只有函数式接口里的方法抛出异常,这里才能抛出异常
       // throw new IOException();
        });
    }
}



``
运行结果:
在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!