Lambda Expressions in Java

Lambda表达式介绍

Lambda表达式是Java函数式编程的重要概念之一。它被用来简化实现函数式接口 (Functional Interface) 的,在进入Lambda的介绍前我们先来回顾一下Interface。

interface接口的基本概念

接口使用来定义一个约定或者说是一种协议,他只提供方法的声明,不提供方法的具体实现,我们还称这样的方法为抽象方法(Abstract Method),具体方法的实现是由实现这个接口的类来提供的。这样将方法的声明与实现分开,业务场景中只需要关心方法的定义,而不需要关心具体的实现,从而实现代码的解耦与模块化。我们来举一个简单的例子:

我们先在包下创建一个Massage接口(接口中定义一个send方法)与两个实现Message接口的实现类并实现send方法,和一个主类。分别如下所示:

//Message接口
public interface Message {
    void send();
}

//实现类 Email
public class Email implements Message{
    private String email;

    public Email(){

    }

    @Override
    public void send() {
        System.out.println("This is a email");
    }
}


//实现类 PhoneNumber
public class PhoneNumber implements Message{
    private String phoneNumber;

    public PhoneNumber()
    {

    }
    @Override
    public void send() {
        System.out.println("This is a phoneNumber");
    }
}

现有一个需求:通过一个方法来发送不同的消息

常规方法实现一定是写一个方法来接收不同的实现类的实例,再调用实现的方法,如下所示:

public class Main {
    public static void main(String[] args) {
        Email email = new Email();
        //PhoneNumber phoneNumber = new PhoneNumber();
        sendMessage(email);
    }

    static void sendMessage(Message message)
    {
        message.send();
    }

}

为什么要引入Lambda表达式

上面的例子中,虽然只是一个方法,但是想要实现它却要经历这么多步骤,未免太麻烦了~

于是Lambda表达式的出现很好的解决了这个问题,如下所示:

public class Main {
    public static void main(String[] args) {
        sendMessage(()->{
            System.out.println("This is a Lambda Email");
        });
    }
    static void sendMessage(Message message)
    {
        message.send();
    }
}

我们不再需要经历实现类的步骤,直接通过Lambda来实现想要的操作,大大简化了代码。

Lambda表达式的语法

1.Lambda表达式的语法为:括号(Parentheses)+连字号(Hyphen)+箭头(Arrow)+大括号(Curly Braces)。Lambda表达式中的括号就是我们一开始写的接口实现类中实现方法的括号,大括号中的就是我们具体要实现的函数体

2.如果Lambda表达式函数体中只包含一个表达式,那么大括号可省略。

public class Main {
    public static void main(String[] args) {
        sendMessage(()->
                System.out.println("This is a Lambda Email"));
    }
    static void sendMessage(Message message)
    {
        message.send();
    }
}

3.如果抽象方法中有一个参数,那么对应的,Lambda表达式中也应该有一个参数:

public interface Message {

    void send(String name);
}

public class Main {
    public static void main(String[] args) {
        sendMessage((name)->
                System.out.println("This is a Email to "+name));
    }

    static void sendMessage(Message message)
    {
        message.send("Lin");
    }

}

在这里插入图片描述

如果只有一个参数,那么类似大括号,也可以将括号去掉:

public class Main {
    public static void main(String[] args) {
        sendMessage(name-> System.out.println("This is a Email to "+name));
        }

    static void sendMessage(Message message)
    {
        message.send("Lin");
    }
}

4.如果抽象方法中有返回值,那么对应的,Lambda表达式中也应该有返回值:

public interface Message {

    String send(String name);
}

public class Main {
    public static void main(String[] args) {
        sendMessage((name)-> {
            System.out.println("This is a Email to "+name);
            return "Success";
        });

        }

    static void sendMessage(Message message)
    {
        System.out.println(message.send("Lin"));
    }

}

在这里插入图片描述

至此,我们再来会看文章一开始的业务,通过一个方法发送不同的信息,我们写了两个实现类Email 和 PhoneNumber 最初我们想要使用PhoneNumber中的实现方法的话就需要new一个PhoneNumber实例 。当我们使用Lambda表达式时,就仅仅需要改一下函数体就行了:

public class Main {
    public static void main(String[] args) {
        sendMessage((name)-> {
            System.out.println("This is a PhoneNumber to "+name);
            return "Success";
        });

        }
    static void sendMessage(Message message)
    {
        System.out.println(message.send("Lin"));
    }
}

在这里插入图片描述

到现在应该可以发现,Lambda表达式让过程变得非常简洁和灵活,不再像传统方式那样需要去写实现类,然后再实例化对象等一系列操作。

函数式接口与Lambda表达式

如果你是第一次了解Lambda表达式那么你一定会感到好奇,Lambda表达式是不是可以用在任意的Interface上呢?它实现的机制又是什么?

事实上,Lambda表达式的使用是有限制的,它只能用于有且只有一个抽象方法的接口上,我们称这样的接口为函数式接口(Functional Interface)。其实这样的限制也很好理解,因为如果一个接口有多个抽象方法的话,再我们使用Lambda表达式时,Java将无法确定我们到底要实现的是哪一个抽象方法,当只有一个抽象方法时就不会出现这样的矛盾。换言之只有函数式接口才可以使用Lambda表达式。再我们文章开头例子中的Message接口中只有一给send()抽象方法,所以Message是一个函数式接口。

如果我们强行在有多个抽象方法的接口上使用Lambda表达式就会出现以下的报错:

在这里插入图片描述

此外还有一些技巧:

如果你在开发中就是认定一个接口它就是函数式接口,那么我们可以在接口上方加入
@FunctionalInterface 注解来表示这个接口为函数式接口。虽然说即使不标注这个注解,Java任然会将只有一个抽象方法的接口认定为函数式接口,但是加上注解也会带来一些益处,例如当我们在加上@FunctionalInterface注解的接口上写了多余的抽象函数,那么会直接爆红,如下图所示:
在这里插入图片描述

此外加上注解也能让其他人能够知道你对这个接口的设计意图。

最后,Lambda表达式归根结底只是一种语法糖,用于简化函数式接口的实现,在Java的函数式编程中起到了关键的作用。Java的标准库中也包含了许多内置的函数式接口,例如Predicate、Function、Consumer,Supplier等,经常与Stream API(点击可进入文章StreamAPI)一起使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值