享学课堂特邀作者:老顾转载请声明出处!

前言

上一篇介绍了lambda表达式的语法,今天老顾继续介绍

Lambda类型

Lambda表达式可以被当做是一个Object。Lambda表达式的类型,叫做“目标类型(target type)”。Lambda表达式的目标类型是“函数接口(functional interface)”

有一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数接口。一般用@FunctionalInterface标注出来(也可以不标)。举例如下

我们看到最后的Comparator接口,声明了两个方法,好像不符合函数接口的定义,但Comparator确实是函数接口。这个是因为equals方法是Object的,所有的接口都会声明Object的public方法(虽然大多是隐式的)。所以,Comparator显式的声明了equals不影响它依然是个函数接口。虽然Lambda虽然可以当作是Object类型,但需要显式转换才行。我们可以用一个Lambda表达式为一个函数接口赋值:

Runnable r1 = () -> {System.out.println("Hello Lambda!");};

然后再赋值给一个Object:

Object obj = r1;

但却不能这样干:

Object obj = () -> {System.out.println("Hello Lambda!");};
// ERROR! Object is not a functional interface!

必须显式的转型成一个函数接口才可以:

Object o = (Runnable) () -> { System.out.println("Hello Lambda!"); };

一个Lambda表达式只有在转型成一个函数接口后才能被当做Object使用。所以下面这句也不能编译:

System.out.println( () -> {} ); //错误! 目标类型不明

必须先转型:

System.out.println( (Runnable)() -> {} ); // 正确

我们可以定义一个无参数,无返回值的接口,类似Runnable

@FunctionalInterface
public  interface  MyRunnable {public  void run();
}

那下面的写法,都是正确的

Runnable r1 = () -> {System.out.println("Hello Lambda!");};
MyRunnable r2 = () -> {System.out.println("Hello Lambda!");};

这说明一个Lambda表达式可以有多个目标类型(函数接口),只要函数匹配成功即可。但需注意一个Lambda表达式必须至少有一个目标类型

Lambda的域以及访问限制

域即作用域,Lambda表达式中的参数列表中的参数在该Lambda表达式范围内(域)有效。在作用Lambda表达式内,可以访问外部的变量:局部变量、类变量和静态变量,但操作受限程度不一

1、访问局部变量

在Lambda表达式外部的局部变量会被JVM隐式的编译成final类型,因此只能访问外而不能修改。

2、访问静态变量和成员变量

在Lambda表达式内部,对静态变量和成员变量可读可写。

内置函数式接口

小伙伴们有没有发现,如果使用Lambda表达式,还是需要我们自己写一个接口定义的,其实很多接口无非是入参类型和返回值不一样而已,所以Java给我们提供了几个常用的标准函数接口:

Consumer< T >con 消费型接口: void accept(T t);Supplier< T >sup供给型接口 : T get();Function< T , R >fun 函数型接口 : R apply (T t);Predicate< T >:断言型接口 : boolean test(T t);

1、Consumer消费型接口

接口中的方法为 void accept(T t),1个参数,无返回值。调用方要传入值,而不需要返回,形象比喻成消费型

这个就是对传入num参数值,进行相关的处理(消费)。到底进行处理,具体就在

(num) -> System.out.println("消费了" + num)

上面的代码中,是一个典型的1个参数,无返回值的消费;如果没有内置的函数接口,那我们就需要自己定义一个,如:

interface  MyConsumer<T>{void doFunction(T t);
}

我们发现和内置函数接口,没有什么区别,就是接口名和方法名称不一样而已,其实本质是一样的,这就是为什么Java会提供一些内置的函数,这样可以减少大量的代码。

2、Supplier供给型接口

接口中的方法 T get(),无参数,有返回值;不需要对方给参数,而是一直返回给对方,形象定义为供给型接口

上面代码就是返回一个新的实体对象。

3、Function函数式接口

接口中的方法 R apply (T t),有参数,有返回值;典型的函数,所以形象比喻成函数型接口

接口实现转换成大写的字符。

4、Predicate断言型接口

接口中方法 boolean test(T t),有参数,返回boolean,是一个条件检查式方法,比喻成断言型接口

内置的函数接口,大大的提高开发的效率,减少了开发代码

方法引用

方法引用是Lambda表达式的一个简化写法,其语法结构为:

ObjectRef::methodName

左边可以是类名或者实例名,中间是方法引用符号“::”,右边是相应的方法名。方法引用可以分为三类。

使用前提:Lambda体中调用方法的参数列表和返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致

静态方法引用

先上一个案例

上面的代码中,我们发现Converter匿名类重载方法中,调用了ReferenceTest的静态方法String2Int。再有函数接口的方法参数类型 和 返回值类型,跟String2Int是一样的,入参为String,返回值为Integer。那我们这个时候可以简化成

直接用静态方法进行赋值,是不是很简洁。

实例方法引用

如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用

对象方法引用

抽象方法的第一个参数类型刚好是实例方法的类型(函数式接口的抽象方法必须要有输入参数)抽象方法剩余的参数恰好可以当做实例方法的参数

如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法的引用(两个条件都要满足)

我们看到第一参数Prod s,和实例对象new Prod是同一个类型;剩余的参数s1,正好是实例方法fun的参数;这样就可以简化成Prod::fun

构造方法引用

如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用,语法【类名::new】

上面是无参数的构造函数,再来看看有参构造函数

到这里,老顾来个方法引用的总结:

总结

Lambda表达式要熟练掌握,是要小伙伴们经常去写,才能够运用自如,代码虽然比较简洁,但确实没有接触的开发人员看上去,就懵逼了,可读性不强。还有Stream的知识点,老顾后面再介绍;今天就分享到这里,谢谢!!!

关注我,还有更多技术干货分享~

表达式类型的实现_程序员如何使代码简洁,Lambda表达式入门之四大引用(下篇)...相关推荐

  1. python绘制生日快乐图片_程序员如何用代码祝自己生日快乐(多用模板)

    原标题:程序员如何用代码祝自己生日快乐(多用模板) 本文教你如何用代码为自己庆祝生日,当然你也可以用来讨好女神,具体如何应用大家可以发散思维,例如情人节给暗恋的女孩发一个 JS 文件过去表白,或者给女 ...

  2. 超有意思的代码注释_程序员搞笑的代码注释:谁的代码注释我都不服,就服你的...

    什么是代码注释,如何在代码中添加注释,相信每一位了解编程的人并不陌生.注释里往往有很多有趣的脑洞和「真心话」.今天我们一起去看看那些6到飞起,被玩坏了的幽默注释吧. 信息量太大的注释系列-- 01 你 ...

  3. 用python表白代码_程序员python表白代码

    原博文 2019-06-13 17:33 − python表白代码 源代码如下: # -*- coding:utf-8 -*- import turtle import time # 画爱心的顶部 d ...

  4. python表白程序源码_程序员python表白代码

    python表白代码 源代码如下: # -*- coding:utf-8 -*- import turtle import time # 画爱心的顶部 def LittleHeart(): for i ...

  5. object转成实体对象_程序员的浪漫,new一个对象

    程序员都喜欢 面向对象编程,但如果你没有对象怎么办?当然是 new 一个对象出来. 面向对象编程 是一种程序设计思想,而不是真正的面向你的对象去编程.如果你真的这么做了,恭喜你获得:你爱我还是爱电脑? ...

  6. java 代码重用需要注意的事项_程序员笔记|编写高性能的Java代码需要注意的4个问题...

    一.并发 无法创建新的本机线程...... 问题1:Java的中创建一个线程消耗多少内存? 每个线程有独自的栈内存,共享堆内存 问题2:一台机器可以创建多少线程? CPU,内存,操作系统,JVM,应用 ...

  7. 程序员过失泄露代码违法吗_软件过失的23种模式

    程序员过失泄露代码违法吗 Ever since the Gang of Four came down from the mountaintop with their stone tablets, li ...

  8. postgresql易学堂_程序员最重要的就是学会“不写代码”

    对什么说"不" 学会说"不"是一个好的开端. 但是到底是对什么说"不",又是什么时候适合说"不"呢? 这的确是大多数程序 ...

  9. 【源码+演示】高考加油!HTML+CSS特效文字祝福_程序员祝福高考学子旗开得胜!

    又是一年盛夏至,愿高三学子高中毕业日,即是高中名校时! 本篇为大家带来3款HTML+CSS制作出的小项目,为高考学子加油助威,愿他们旗开得胜,金榜题名![源码+演示]高考加油!HTML+CSS特效文字 ...

最新文章

  1. mysql双主使用reset master清除日志要小心
  2. 价值6.11亿美元的入侵工具无人问津
  3. Intent 匹配规则
  4. XMLIOC案例-编写spring的Ioc配置
  5. linux nc命令测试端口,Linux和Windows下的NC(Netcat)命令测试端口连通性
  6. [vue] 说下你的vue项目的目录结构,如果是大型项目你该怎么划分结构和划分组件呢?
  7. APP自动化测试系列之3种元素定位工具
  8. vscode使用vuex数据持久化插件(vuex-persistedstate)
  9. C语言基础教程之递归
  10. java和jsp交互 structs_Struts与jsp+javabean+servlet区别
  11. 关于防止表单form重复提交的方式
  12. Linux gcc编译时强制链接并依赖一个库(即使未使用)
  13. Mysql SQLyog 使用详解
  14. modelsim安装教程
  15. 视易服务器查看硬盘状态,Linux服务器使用Smartmontools检测硬盘状况 | 厘米天空
  16. 手机安全修改IMEI的方法
  17. C语言选择题(含答案)
  18. zabbix报警 Lack of free swap space on zabbix
  19. 7-35 英文字母的大小写转换
  20. 51单片机可以用来练手的60个小设计

热门文章

  1. 分布式Ehcache Terracotta使用
  2. NHibernate2.1新特性之entity-name
  3. Linux设置界面或命令行启动
  4. WIN7 不用格式化磁盘怎么把FAT32系统改成NTFS系统
  5. 仿Gin搭建自己的web框架(五)
  6. php分布式redis实现session共享
  7. Java的三大特性之继承
  8. python基础===pip安装模块失败
  9. VRRP+MSTP 实现流量分流与核心层备份
  10. IP_FORWARD转发