其实很久前已经学习过了Lambda表达式,但是学习后没有多少使用的机会,久而久之也就忘记(惭愧)。最近新的项目用的jdk8所以准备再学习一次,写下文章也是为了记录,方便以后再忘的时候,不用到处找资料(旁白:这么丢人的事,能别到处说吗)。

语法

(参数) -> 表达式​或​(参数) -> {表达式}

第一个Lambda表达式

public class Java8Lambda {​    @Test    public void test1() {        // lambda表达式        Greeting helloLambda = (name) -> "Hello! " + name;        // 调用方法        System.out.println(helloLambda.sayHello("Lambda"));    }​    interface Greeting {        String sayHello(String name);    }}

输出结果:

Hello! Lambda

Lambda表达式可以看成是匿名类一点点演变过来

  1. 匿名类的写法

@Testpublic void test2() {    // 匿名类的写法    Greeting helloLambda = new Greeting() {        @Override        public String sayHello(String name) {            return "Hello! " + name;        }    };    // 调用方法    System.out.println(helloLambda.sayHello("Lambda"));}

设计匿名内部类的目的,就是为了方便java程序员将代码作为数据传递。不过匿名内部类还是不够简便。

  1. 去除外壳,保留方法参数和方法体,并在参数和方法体之间加上符号->(这里已经变成Lambda了,但不是最简洁的,请往下看)

@Testpublic void test3() {    // 去除外壳,保留方法参数和方法体,并在参数和方法体之间加上符号->    Greeting helloLambda =(String name) -> {            return "Hello! " + name;        };    // 调用方法    System.out.println(helloLambda.sayHello("Lambda"));}
  1. 去除return和{}

@Testpublic void test4() {    // 去除return和{}    Greeting helloLambda =(String name) -> "Hello! " + name;    // 调用方法    System.out.println(helloLambda.sayHello("Lambda"));}
  1. 去除参数类型和圆括号(只有一个参数的时候,才可以去掉圆括号)

@Testpublic void test5() {    // 去除参数类型和圆括号(只有一个参数的时候,才可以去掉圆括号)    Greeting helloLambda = name -> "Hello! " + name;    // 调用方法    System.out.println(helloLambda.sayHello("Lambda"));}

从test2到test5代码一步步变的简介紧凑,与匿名类相比Lambda更加简洁

函数式接口

函数式接口是只有一个抽象方法的接口,使用Lambda表达式的接口都是函数式接口。

Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。

函数式接口还带有一个注解@FunctionalInterface,这个注解帮助开发者判断接口是否是函数式接口,如果接口不是函数式接口,编译器将会返回一个提示错误。例如:Multiple non-overriding abstract methods found in interface com.straymalone.java8demo.Java8Lambda.Greeting,表明存在多个抽象方法。注意,@FunctionalInterface不是必须的,但是对于为此设计的接口而言,使用它是比较好的做法。它就像@Override注解表示方法被重写了。

类型推断

某些情况下,用户需要手动指明Lambda参数的类型,例如:

@Testpublic void test6() {    BinaryOperator<Long> addLongs = (x, y) -> x + y; // 去掉<Long>会报错哦    // 调用方法    System.out.println(addLongs.apply(2L, 3L));}

这时将泛型<Long>去掉编译器将会报错,提示如下:

Operator '+' cannot be applied to 'java.lang.Object', 'java.lang.Object'

BinaryOperator 毕竟是一个具有泛型参数的函数接口, 该类型既是参数 x 和 y 的类型, 也是返回值的类型。 上面的例子中并没有给出变量add 的任何泛型信息, 给出的正是原始类型的定义。 因此, 编译器认为参数和返回值都是java.lang.Object 实例。

所以这个时候如果没有泛型就会编译报错。

Lambda表达式的重要特征

  • 可选的类型声明:有时省略类型信息可以减少干扰,更易弄清状况;而有时却需要类型信息帮助理解代码

  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号

  • 可选的大括号:如果主题包含了一个语句,就不需要使用大括号

  • 可选的返回关键字:如果主题只有一个表达式返回值则编译器会自动返回值,如果使用大括号说明不止一个语句,必须声明返回值。

  • 可选的注解@FunctionalInterface:检测接口是否是函数式接口

参考资料

  1. http://how2j.cn/p/2791

  2. https://www.w3cschool.cn/java/java8-lambda-expressions.html

  3. 《Java 8函数式编程》

  4. 《Java 8实战》

java8(一)Lambda表达式的更多相关文章

  1. Java8中Lambda表达式的10个例子

    Java8中Lambda表达式的10个例子 例1 用Lambda表达式实现Runnable接口 //Before Java 8: new Thread(new Runnable() { @Overri ...

  2. java8的lambda表达式,将List<DTO> 转为 List<DO>

    将List<PhoneDTO>转为List<PhoneDO>,通过java8的lambda表达式来操作,比传统的for循环精简很多: /** * List<PhoneDT ...

  3. java8的lambda表达式

    关于java8的lambda表达式 lambda表达式一般用于接口,因为lambda表达式是函数式编程. 1.有且仅有一个抽象方法被称为函数式接口,函数式接口可以显示的被@FunctionalInte ...

  4. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  5. java8之lambda表达式(1)-基本语法

    lambda表达式,即带有参数的表达式,为更清晰地理解lambda表达式,先看如下例子: (1) class Student{ private String name; private Double ...

  6. java8之lambda表达式入门

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ privat ...

  7. JAVA8之lambda表达式具体解释,及stream中的lambda使用

    前言: 本人也是学习lambda不久,可能有些地方描写叙述有误,还请大家谅解及指正! lambda表达式具体解释 一.问题 1.什么是lambda表达式? 2.lambda表达式用来干什么的? 3.l ...

  8. 十分钟学会Java8的lambda表达式和Stream API

    01:前言一直在用JDK8 ,却从未用过Stream,为了对数组或集合进行一些排序.过滤或数据处理,只会写for循环或者foreach,这就是我曾经的一个写照. 刚开始写写是打基础,但写的多了,各种乏 ...

  9. java8中Lambda表达式和Stream API

    一.Lambda表达式 1.语法格式 Lambda是匿名函数,可以传递代码.使用“->”操作符,改操作符将lambda分成两部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 ...

  10. Java8之lambda表达式

    一.什么是lambda表达式? Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码 ...

随机推荐

  1. 100天搞定机器学习|Day11 实现KNN

    机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机器学习|D ...

  2. Codeforces 755E:PolandBall and White-Red graph(构造+思维)

    http://codeforces.com/contest/755/problem/E 题意:给出n个点和一个距离d,让你在这个n个点的图里面构造一个子图,使得这个子图的直径和补图的直径的较小值为d, ...

  3. 性能测试即服务-docker部署jmeter及.netcore应用

    前言 现在各种业务都追求上云,通俗的讲,“XX即服务”,作为一名专职的性能测试调优人员的我,由于会点三脚猫的开发功夫,“性能测试即服务”这种开发大任就落到我头上了,先做一个能完成核心压测功能的基础版. ...

  4. (转)VSCode调试go语言出现:exec: "gcc": executable file not found in %PATH%

    原文:https://www.cnblogs.com/zsy/p/5958170.html 1.问题描述 由于安装VS15 Preview 5,搞的系统由重新安装一次:在用vscdoe编译go语言时, ...

  5. WebLogic 任意文件上传远程代码执行_CVE-2018-2894漏洞复现

    WebLogic 任意文件上传远程代码执行_CVE-2018-2894漏洞复现 一.漏洞描述 Weblogic管理端未授权的两个页面存在任意上传getshell漏洞,可直接获取权限.Oracle 7月 ...

  6. akka 集群分片

    akka 集群 Sharding分片 分片上下级结构 集群(多台节点机) —> 每台节点机(1个片区) —> 每个片区(多个分片) —> 每个分片(多个实体) 实体: 分片管理的 A ...

  7. KETTLE数据上传

    1.     KETTLE简介 一种ETL工具,ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(l ...

  8. Ui自动化测试上传文件方法都在这里了

    前言 实施UI自动化测试的时候,经常会遇见上传文件的操作,那么对于上传文件你知道几种方法呢?今天我们就总结一下几种常用的上传文件的方法,并分析一下每个方法的优点和缺点以及哪种方法效率,稳定性更高 被测 ...

  9. 【最小生成树之Kruskal算法】

    看完之后推荐再看一看[最小生成树之Prim算法]-C++ 定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以用kr ...

  10. redis集群(单机6节点实现)

    Redis集群搭建与简单使用 1.介绍安装环境与版本: 1)Redis使用的是Redis-3.2.8版本. 2)用一台虚拟机模拟6个节点,三个master节点,三个slave节点.虚拟机使用CentO ...