前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lambda表达式概述

Lambda表达式概述

作者头像
IT架构圈
发布2018-06-01 12:23:07
3010
发布2018-06-01 12:23:07
举报
文章被收录于专栏:IT架构圈IT架构圈

一、Lambda表达式的基本形式 Labmda表达式实际上是一个经过简化之后的函数,它省略函数名,用 -> 符号将参数和函数体连接起来。

(arg1,arg2) -> { //函数体 } 说明: 1.参数:如果没有参数,就用()表示;如果只有一个参数,那么()可以省略。 2.函数体:如果函数体只有一条语句,那么{}可以省略。

二、Lambda表达式的作用 ??在Java中,有些接口只有一个方法,比如很常见的Runnable接口就只有一个run()方法。如果要使用这个接口,一般的做法是写一个实现类:

代码语言:javascript
复制
//Runnable接口的实现类
class RunnableImpl implements Runnable
{
    @Override
    public void run() {
        System.out.println("Hello,world!");
    }
}
public class NoLambdaTest {
    public static void main(String[] args) {
        RunnableImpl runnable = new RunnableImpl();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

但是这种做法比较费事,所以更常见的做法是把Runnable接口的实现写成匿名内部类:

代码语言:javascript
复制
public class NoLambdaTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("Hello,world!");
            }
        });
        thread.start();
    }
}

但不管是哪种写法,都仅仅是为了实现一个方法,为此而写出一个类是很不划算的;Lambda表达式就可以解决这个问题。 之前说过,Lambda表达式实际上就是一个经过简化的函数,因此可以使用Lambda表达式来实现Runnable接口中的run()方法:

代码语言:javascript
复制
public class LambdaTest {
    public static void main(String[] args) {
        //用Lambda表达式来实现接口
        Runnable runnable = () -> System.out.println("Hello,world!");
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

在上面的示例中,Runnable runnable = () -> System.out.println("Hello,world!");就使用了Lambda表达式。run()方法没有参数,因此->的左边是一个();->的右边就是run()的函数体。注意,在实现了run()方法的同时,还创建了一个Runnable的实例runnable。 因此,Lambda表达式的作用就是可以很方便地实现只有一个方法的接口,使代码变得简洁。

说明: 1.只有一个方法的接口教做函数接口。Java 8提供了java.util.function包,这个包里有很多函数接口,都是配合Lambda表达式来使用的。 2.严格地说,Runnable并不是函数接口,只不过是它也正好只有一个方法。

三、使用Lambda表达式时需注意的细节 1.只能引用final域 假设在Lambda表达式需要使用一个变量,那么这个变量就必须是final的,否则编译无法通过。

代码语言:javascript
复制
public class LambdaTest {
    public static void main(String[] args) {
        final int sum = 3;
        Runnable runnable = () -> System.out.println("1 + 2 = " + sum);
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

将sum前面的final修饰符去掉,编译还是可以通过;但如果像下面所展示的那样做,编译无法通过:

代码语言:javascript
复制
public class LambdaTest {
    public static void main(String[] args) {
        int sum = 3;
        sum = 6;
        Runnable runnable = () -> System.out.println("1 + 5 = " + sum);
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

运行的话就会抛出一个异常,根源还是在于Lambda表达式只能引用final变量。即使一个变量没有用final修饰,但如果它只初始化了一次且没有再次赋值,那么这个变量在逻辑上依然是final的;但如果在这个变量初始化之后再次赋值,它就不是final的。因此,最安全的做法就是确保Lambda表达式只会引用final变量。

2.类型推断 如果将要实现的函数接口是泛型的,那么javac可以根据函数接口使用的具体类型来推断出参数类型。比如,Java 8提供了一个函数接口Predicate,这个接口的方法是test(T t),用来检测参数t是否满足某些条件,返回值是boolean。用Lambda表达式来实现这个接口,就可以写成:

代码语言:javascript
复制
public class LambdaTest {
    public static void main(String[] args) {
        Predicate<Integer> atLeast5 = x -> x > 5;
        Scanner scan = new Scanner(System.in);
        int num = scan.nextInt();
        boolean flag = atLeast5.test(num);
        if(flag)
            System.out.println("This number is more than 5.");
    }
}

编译器可以进行类型推断,因此无需指明x的类型。但要注意,推断的前提是已经指定这个泛型接口的具体类型 ,因此,Predicate这里的类型是不可省略的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程坑太多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档