Java8-Lambda表达式

Lambd

lambda表达式是java8的新特性,可使用函数式接口替换掉原来的匿名内部类java

lambda的本质就是引用一个已经具体实现的方法来完成对函数式接口抽象方法的具体实现ide

例如如今有一个接口,里面只有一个求和方法函数

public interface Mylambda {
    int sum(int a,int b);
}

咱们如今想要使用这个方法,有三种方式学习

  1. 建立一个类实现这个接口
  2. 匿名内部类
  3. 使用lambda函数式接口

第一种方法就不说了,来看使用匿名内部类测试

Mylambda myLambda=new Mylambda() {
    @Override
    public int sum(int a, int b) {
        return a+b;
    }
};

而后调用myLambda的sum方法能够作到求和的操做code

再来看看lambda对象

Mylambda myLambda=(int a,int b)->{
    return a+b;
};

()->{} 什么意思呢? 咱们来看看lambda是如何使用的接口

() 里面是传入的参数get

{} 里面为方法体具体操做io

须要注意的点

  1. lambda只能用于只有一个方法的接口
  2. 最好在接口上添加注解@FunctionalInterface来代表这是一个函数式接口
  3. 参数类型由于已经在接口中定义,那么传入参数时能够不用写参数类型,要么参数都写参数类型,要否则都不写参数类型
  4. 参数的数量,类型,顺序必须和接口中一致

那么lambda就这些吗? 固然不是,还能够简化以及拆分方法

简化

若是方法体中就只有一条return语句,例如上面sum方法中,那么在lambda表达式中能够省略大括号以及return

public static void main(String[] args) {
    Mylambda mylambda = (a,b) -> a + b;
}

若是参数只有一个,能够省略小括号

例以下面这个接口,咱们并无作任何操做,只是将传入参数原封不动返回,只是为了学习使用

@FunctionalInterface
public interface MyLambda2 {
    int print(int i);
}

使用

public static void main(String[] args) {
    MyLambda2 myLambda2= i -> i;
}

是否是看的有点蒙呢,不简化就是

MyLambda2 myLambda2= (i) -> {
    return i;
};

由于参数只有一个,并且返回值也只有一条return语句,因此省略了传入参数的小括号以及方法体的大括号和return关键字

这里也有个须要注意的点 : 方法体的大括号和return语句要么都省略,不能只省略一个

若是方法中仅仅想返回一个对象,不作任何其余操做,还能够简化

//接口============
@FunctionalInterface
public interface MyLambda2 {
    User getUser();
}
//使用,未简化前===========
public static void main(String[] args) {
    MyLambda2 myLambda=()->{
        return  new User();
    };
}
//再根据参数和方法体简化=====
public static void main(String[] args) {
    MyLambda2 myLambda2=()->new User();
}
//使用,简化后
public static void main(String[] args) {
    MyLambda2 myLambda=User::new;
}

上面两个使用估计均可以看懂,可是最后一个User::new 估计有点蒙,什么意思呢?

在开头就讲过 lambda的本质就是引用一个已经具体实现的方法来完成对函数式接口抽象方法的具体实现

而lambda建立User对象说白了就是调用User的构造方法,而lambda调用对象的构造方法的语法就是 类型::new也就是上面写的User::new,这种方式称为构造器引用

那么若是想经过lambda调用对象的有参构造呢?

很遗憾,不能经过这种方式来调用对象的有参构造,若是想经过lambda调用,咱们能够稍微简化为下面这种

//接口========
@FunctionalInterface
public interface MyLambda2 {
    User getUser(String name,int age);
}
//测试=============
public static void main(String[] args) {
    MyLambda2 myLambda2=(name,age)->new User();
}

拆分,也就是方法引用

那么若是一个方法咱们常常使用该怎么办呢,难道每次都去复制原来的lambda表达式吗?

能够将经常使用的方法单独拆分出来,每次lambda表达式去调用这个方法便可

咱们以上面的sum接口为例 :

//接口===================
@FunctionalInterface
public interface Mylambda {
    int sum(int a,int b);
}
//测试==================
public static void main(String[] args) {
    Mylambda mylambda = (a,b)-> doSum(a,b);
    int sum = mylambda.sum(2, 5);
}
//抽取出的方法( 注意是静态调用静态,若是是普通方法须要建立对象 )===============
public static int doSum(int a,int b){
    return a+b;
}

咱们将求和的操做单独拆分为一个方法,每次使用时只须要调用这个方法便可

() -> xxx();

也就是说lambda不只能够直接写方法具体细节,也能够调用其余方法,须要注意的时调用的方法返回值必须和接口定义返回值一致
固然,调用拆分的方法也能够简化,使用方法以下

静态类 类名::方法

非静态 对象::方法

对于静态的方法引用

//接口=======
@FunctionalInterface
public interface Mylambda {
    int sum(int a,int b);
}
//测试类名为Test=========
public static void main(String[] args) {
    Mylambda myLambda=Test::doSum;
}
//拆分的方法========
public static int doSum(int a,int b){
    return a+b;
}

对于非静态方法引用

//接口=======
@FunctionalInterface
public interface Mylambda {
    int sum(int a,int b);
}
//测试类名为Test=========
public static void main(String[] args) {
    Test test = new Test();
    Mylambda myLambda=test::doSum;
}
//拆分的方法========
public static int doSum(int a,int b){
    return a+b;
}

二者区别仅仅是在于对象::方法类::方法,由于非静态类须要建立出对象才能够调用方法

当使用简化后的调用方法那么会自动匹配参数类型,数量和顺序,因此更加要严谨仔细,确保参数一一对应

再说一遍吧,lambda的本质就是引用一个已经具体实现的方法来完成对函数式接口抽象方法的具体实现,那么如今再来看这句话是否是清楚不少呢

本文仅我的理解,若是有不对的地方欢迎评论指出或私信,谢谢٩(๑>◡<๑)۶

相关文章
相关标签/搜索