专栏首页好好学java的技术栈你真的了解 Java 8 中的 lambda 表达式、方法引用、函数式接口、默认方式、静态方法吗

你真的了解 Java 8 中的 lambda 表达式、方法引用、函数式接口、默认方式、静态方法吗

lambda 表达式

lambda 表达式在项目中也是用到了,这种新的语法的加入,对于使用 Java 多年的我,我觉得是如虎添翼的感觉哈,这种新的语法,大大的改善了以前的 Java 的代码,变得更加的简洁,我觉得这也是为什么 Java8 能够很快的流行起来的原因吧。

这里我们用几个以前的经典的 Java 的写法和用 lambda 表达式的方式进行对比。

线程的用法

原始的线程用法

1//使用匿名内部类的方式启动多线程
2        new Thread(new Runnable() {
3            @Override
4            public void run() {
5                System.out.println("这是使用匿名内部类的方式。。。");
6            }
7        }).start();

lambda 表达式

1//使用lambda表达式方式
2        new Thread(() -> {
3            System.out.println("这是使用lambda表达式的方式。。。");
4        }).start();

你会发现,用 lambda 表达式的方式能够写更少的代码,看起来也会更加的舒服和简洁。

这里没有使用参数,只是一个简单的例子。

我们再看一个例子。

遍历方式

原始方式

1//原始方式
2        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
3        for (int i : list) {
4            System.out.println(i);
5        }

lambda 表达式方式

1//使用lambda表达式代替foreach循环
2        Stream.of(1, 2, 3, 4, 5).forEach((x) -> {
3            System.out.println(x);
4        });

在原始的方式中,我们一般使用 foreach 的方式进行遍历,有了 Java8 的方式之后,我们可以用 forEach 方法,然后,再用 lambda 表达式的方式进行遍历,也让原来的方式变得更加的简洁。

在这个例子中,我们加了一个参数,在()中间我们加了一个 x ,代表的意思其实是:通过 forEach 方法,我们把一个元素已经赋值到 x 中了,拿到这个 x ,我们就可以输出结果。

总结

lambda 的使用方式其实很简单,可以总结为下面的方法。

1([参数可选,...]) -> {
2}

方法引用

方法引用其实是 lambda 表达式的部分的简化,也就是为了简化 lambda 表达式而存在的感觉,下面我们还讲讲怎么使用方法引用

 1/**
 2     * @return void
 3     * @Author ouyangsihai
 4     * @Description 方法引用测试
 5     * @Date 10:23 2019/5/14
 6     * @Param []
 7     **/
 8    @Test
 9    public void test_method_reference() {
10        //使用lambda表达式
11        Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
12                .map(s -> s.length()) //lambda
13                .forEach((x) -> {
14                    System.out.println(x);
15                });
16
17        //使用静态方法引用
18        Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
19                .map(String::length) //静态方法引用
20                .forEach((x) -> {
21                    System.out.println(x);
22                });
23
24        //使用实例方法引用
25        Stream.of(
26                new ClassMate("1", "欧阳思海"),
27                new ClassMate("2", "sihai")
28        ).map(ClassMate::getName)//实例方法引用
29                .forEach(x -> {
30                    System.out.println(x);
31                });
32
33    }

在第一个测试中,我们用的是 lambda 表达式来获取每个字符串的长度

1s -> s.length()

在第二个测试中,我们使用的是静态方法引用来获取每个字符串的长度

1String::length

在第三个测试中,我们使用的是实例方法引用。

1ClassMate::getName

解释 ① map 方法是映射的意思。 ② forEach 方式是遍历每一个元素。 ③ ClassMate 是一个包含 id 和 name 的简单 po 类。

通过上面这个例子,基本上我们就知道怎么使用方法引用了。下面我们进行一个小的总结。

总结 ① 使用方法

1类名::方法名

② 方法可以是:静态方法,实例方法

构造函数引用

在上面我们讲了方法引用的基本使用方法,其实除了方法引用以外,还有构造函数引用,回想一下,以前我们创建对象是怎么做?是不是需要 new 一个对象呢,那么现在用构造函数引用又是怎么做的呢?

下面我们用一个例子讲解一下,在这个例子中,对象还是使用上面的 ClassMate

 1/**
 2     * @return void
 3     * @Author ouyangsihai
 4     * @Description 构造函数引用测试
 5     * @Date 10:23 2019/5/14
 6     * @Param []
 7     **/
 8    @Test
 9    public void test_method_reference2() {
10        //使用lambda表达式
11        Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
12                .map(s -> new ClassMate(s)) //lambda
13                .collect(Collectors.toList());
14
15        //使用构造函数引用
16        Stream.of("A", "BB", "CCC", "DDDD", "FFFFF")
17                .map(ClassMate::new) //构造函数引用,由上下文决定用哪一个构造函数
18                .collect(Collectors.toList());
19    }

① 第一个我们使用的是 lambda 表达式进行创建对象的 s -> new ClassMate(s)。 ② 第二个我们使用的是构造函数引用创建对象的 ClassMate::new 。 ③ 我们发现构造函数引用:类名::new ,然后对于使用哪一个构造函数是由上下文决定的,比如有一个参数和两个参数和无参数的构造函数,会自动确定用哪一个。

接口

在 Java 8 之前的接口是不能有实现的,只能定义抽象方法,然而,在 Java 8 以后,增加了一个新的功能,可以添加实现,可以定义默认方法,可以定义静态方法

函数式接口

什么是函数式接口呢?

这个名词在 Java 中以前是很少听到的,但是正是有了 Java 8 的横空出世,函数式编程也变得熟悉了。

在一个接口中我们以 @FunctionalInterface 注解声明一个接口,并且接口中只有一个抽象方法,那么我们就叫做这是一个函数式接口

 1/**
 2 * @ClassName FunctionalInterfaceTest
 3 * @Description
 4 * @Author 欧阳思海
 5 * @Date 2019/5/14 10:39
 6 * @Version 1.0
 7 **/
 8@FunctionalInterface
 9public interface FunctionalInterfaceTest {
10    //继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口
11    void test(String s);
12}

① 上面的接口中只有一个抽象方法,所以这是一个函数式接口。 ② 如果上面接口中再加一个抽象方法,那么就不是函数式接口了。

下面,我们再通过继承来继承这个接口。

 1/**
 2 * @ClassName FunctionalTest
 3 * @Description
 4 * @Author 欧阳思海
 5 * @Date 2019/5/17 17:26
 6 * @Version 1.0
 7 **/
 8public interface FunctionalTest extends FunctionalInterfaceTest{
 9
10    int test2();
11}

① 我们继承了上面的接口,并且加了一个 test2 方法。 ② 这里注意,如果一个接口集成现有的函数式接口后,又加了其他的抽象方法,这个接口就不是函数式接口了。

默认方法

默认方法很简单,用 default 声明即可。

 1/**
 2 * @ClassName FunctionalInterfaceTest
 3 * @Description
 4 * @Author 欧阳思海
 5 * @Date 2019/5/14 10:39
 6 * @Version 1.0
 7 **/
 8@FunctionalInterface
 9public interface FunctionalInterfaceTest {
10    //继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口
11    void test(String s);
12
13    //默认方法
14    default String getStr(){
15        return null;
16    }
17}

① 在接口中添加了一个默认方法。并且实现了方法。

静态方法

默认方法很简单,用 static 声明即可。

 1/**
 2 * @ClassName FunctionalInterfaceTest
 3 * @Description
 4 * @Author 欧阳思海
 5 * @Date 2019/5/14 10:39
 6 * @Version 1.0
 7 **/
 8@FunctionalInterface
 9public interface FunctionalInterfaceTest {
10    //继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口
11    void test(String s);
12
13    //静态方法
14    static String getStr2(){
15        return null;
16    }
17
18    //错误用法
19    default static String getStr3(){
20        return null;
21    }
22}

① 实现的静态方法,用 static 声明。 ② 注意不能同时使用 default 和 static 声明。

本文分享自微信公众号 - 好好学java(SIHAIloveJAVA)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Tomcat部署时war和war exploded区别以及平时踩得坑

    (1)war模式这种可以称之为是发布模式,看名字也知道,这是先打成war包,再发布;

    Java高级攻城狮
  • JavaScript中的垃圾回收和内存泄漏

    程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。所谓的内存泄漏简单来说是不再用到的内存,没有及时释放。为了更好避免内存泄漏,我们先介绍J...

    Fundebug
  • 在面试中如何展示虚拟机和内存调优技能

    在这个寒冬中,我们得不断提升自己的能力,所以这次,我就针对“虚拟机描述”这个点扩展出去,具体讲些在面试中展示虚拟机内存调优能力的话术。

    本人秃顶程序员
  • Java开发转行大数据,需要做到哪几点?

    Java开发转大数据开发要做到几点?假设你有Java基础选择了自学大数据,而对于完全没有编程和Java基础的人来说,自学绝对是浪费时间和精力的事情。Jav...

    用户5265382
  • 增加MATLAB获取其他程序窗体位置功能

    一样的调用win32程序,都需要窗体的类名、窗体名称作为参数。Java接口用的传值方式、需要创建一个矩形对象传入函数,执行后矩形对象里面就是返回值;Python...

    万木逢春
  • MATLAB调用Java操作键盘鼠标

    MATLAB在plot之后得到图像figure窗体的句柄,可以操作figure修改尺寸以及各种参数。

    万木逢春
  • 11万份测试告诉你,今年该学什么编程技能才能找到好工作

    报告主要分为两大部分:技术招聘的技能解读和技术招聘的地理分布。本文将重点介绍第一部分。

    机器之心
  • 增加MATLAB屏幕截图功能

    万木逢春
  • 我们能从 InteliJ IDEA 中学到什么?

    最近因为工作的关系,要将 Eclipse 的插件升级为 IDEA 插件。升级过程中,对 IDEA 插件做了些学习和研究,希望通过本文,对“为什么收费的 Inte...

    kirito-moe
  • MATLAB调用Python操作键鼠

    借助Java实现Windows操作MATLAB调用Java操作键盘鼠标不需要另行安装其他程序,不过现在Python语言风头正劲,运用Python也可以直接m文件...

    万木逢春

扫码关注云+社区

领取腾讯云代金券