今夜我懂了Lambda表达式_解析
现在时间午夜十点~ 此刻的我血脉喷张,异常兴奋:因为专注得学习了一把java,在深入集合的过程中发现好多套路配合Lambda表达式真的是搜椅子,so开了个分支,决定从“只认得”,变为“我懂得”
start:
先上一盘代码,对应来解析:
/*我是一个接口*/
interface Rap{
void show();
//注意:虽然没有用abstract修饰方法,但它真是抽象方法,我特意去试了下,应该是没有方法体的方法默认在前面加abstract
}
/*我是二个接口*/
interface Basketball{
void play(String name);
//注意:同上
}
/*我是一个测试类*/
public class LambdaTest(){
//调用下面两个方法,要传递对应类型的对象(也就是我上面定义的接口类型),那得要创建实例才行啊,哈哈看看Lambda的骚操作
public void method1(Rap r){
//这是接口中的抽象方法,必须要接口的实现类进行重写才可使用
r.show();
}
public void method2(Basketball b){
//这是接口中的抽象方法,必须要接口的实现类进行重写才可使用
b.play("坤坤")
}
public static void main(String[] args){
LambdaTest lt = new LambdaTest();
//Lambda开始操作
//调用方法1
//功能代码语句只有一句,可省略大括号
System.out.println(lt.method1(() -> System.out.println("我是练习时长两年半的..你猜我是谁"));
//调用方法2
//功能代码语句有多句,要加大括号
System.out.println(lt.method2(name) -> {
System.out.println("请叫我:"+name);
System.out.println("擅长唱跳Rap篮球")
});
}
}
解析:
- 首先此例将Lambda表达式作为实现了接口的实例对象,传递给了方法(不是对应类型的对象的话方法没有形参,无法调用);
- 所以可以确定Lambda表达式可以充当匿名对象
- 再看method1和method2两个方法内调用的都是我定义的两个接口中唯一的抽象方法,所以必定要要接口的实现类去重写接口中的抽象方法;
- 所以可以看出Lambda表达式可以充当匿名方法
小技巧:箭头(->) 左边的是参数,右边的就是方法体
从上也可以看出Lambda表达式的使用的限制:
- Lambda表达式的目标类型必须是明确的函数式接口(目标类型就是被他实现的接口类型)
- Lambda表达式只能为函数式接口创建对象:由于其只能实现一个方法,因此它只能位为只有一个抽象方法的接口(函数式接口)创建对象
为了确保目标类型是一个明确的函数式接口,可以这样设计代码:
- 将Lambda表达式赋值给函数式接口类型的变量
- 将Lambda表达式作为函数式接口类型传递给某个方法(如上面的例子)
- 使用函数接口对Lambda表达式进行强制类型转换
- 值得一提的是,同样的Lambda表达式,其目标类型是可变的,也就是说通用的,这个接口可以用,换个接口也可以;当然前提是目标类型(接口)中的抽象方法形参列表相同;就好比我有两个函数式接口,都没有参数,然后我写个表达式并进行强制类转换,此时可以这两个接口的类型都可以用
补充:java8中给函数式接口提供了@FunctionalInterface注解,检查接口必须是函数式接口
引用
Lambda表达式的代码块只有一条语句时,可以省略"{ }"花括号,其实还可以写的更简洁:使用方法引用 和 构造器引用,符号为两个英文冒号:::
有四种引用方式:
引用类方法
语法:类名 :: 类方法
/*定义一个函数式接口,将String类型数据转换成Integer*/
interface Convert{
//抽象方法,返回类型为Integer
Integer Convert(String from);
}
/*使用Lambda表达式的写法创建Convert(目标类型)对象,就是获取接口实现类的实例*/
Convert c1 = from -> Integer.valueOf(from);
/*使用引用类方法的方式获取Convert对象*/
Convert c2 = Integer :: valueOf;
//是不是相当简洁,对比可以看出是将参数省略了,这就是其魅力所在
//调用接口中抽象方法时,所传递的参数会默认传递给该类方法,即valueOf
引用特定对象的实例方法
语法:特定对象 :: 实例方法
/*Lambda方式创建Coverter对象,借用上面的接口*/
Converter c = from -> "fkit.org".indexOf(from);
/*方法引用代替Lambda表达式获取对象*/
Converter c = "fkit.org" :: indexOf;
引用某类对象的实例方法
语法:类名 :: 实例方法
/*函数式接口;从指定的位置开始b,截取指定字符串a,指定长度c*/
interface MyTest{
String test(String a,int b,int c);
}
/*Lambda表达式方式获取接口MyTest的实现对象*/
//有返回值的情况下会将此Lambda表达式作为返回值
MyTest mt = (a,b,c) -> a.substring(b,c);
/*换成引用方法的方式*/
//将函数式接口中实现方法的第一个参数作为调用者
//后面的参数全部传递给方法作为参数
MyTest mt = String :: substring;
/*使用接口实例调用接口方法*/
String str = mt.test("我是测试字符串哈哈",2,5);
System.out.println(str);//打印结果:测试字符串
- 引用构造器
语法:类名 :: new
/*定义一个函数式接口,传递参数,调用MyClass类中对应的带参构造器*/
interface MyTest{
MyClass creat(String str);
}
/*使用Lambda表达式获取接口实例对象*/
MyTest mt = str -> new MyClass(str);
/*使用引用构造器方式*/
//函数式接口的抽象方法的所有参数都会传递给对应的构造函数
MyTest mt = MyClass :: new;
/*调用测试*/
MyClass mc = mt.creat("调用对应构造器创建对象");
扩展
Lambda表达式和匿名内部类的联系
- 相同点:都可以访问父类的成员,且被访问的成员默认修饰final,即不可二次赋值;都可以生成对象,并从接口中继承默认的方法
- 区别:Lambda表达式只能为函数式接口创建实例(只有一个抽象方法的接口),且只能实现其中的抽象方法,其他方法免谈
使用Lambda配合java.util.function中预定义的函数式接口
- XxxFunction:这类接口中包含一个apply()抽象方法,用于对参数进行处理、转换
- XxxConsumer:包含一个accept()抽象方法,与上面的apply()类似,也用于处理数据,只是不会返回处理结果
- XxxPredicate:包含一个test()抽象方法,用来对参数进行条件判断(常用与过滤集合元素)
- XxxSupplier:包含一个getAsXxx()抽象方法,该方法会根据所定义的逻辑算法返回一个数据
上面接口中的抽象方法都可以用Lambda表达式来实现方法的逻辑了
总的来说,Lambda表达式简洁,还能装逼。但是可读性有点差咯,不说别人来看,自己写的时间长了一时半会还看不懂...所以建议对于常用的函数式接口的实现可以用Lambda实现,或者注释满上,又或者我就要写别人看不懂的代码,nb(我喜欢~)
今夜我懂了Lambda表达式_解析的更多相关文章
- Lambda表达式树解析(下)
概述 前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正 ...
- Lambda表达式树解析(下)包含自定义的provider和查询
概述 前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正 ...
- 【Java】Java8新增的Lambda表达式_学习笔记
一.Lambda表达式可以简化创建匿名内部类对象 1.不需要new XXX(){}这种繁琐代码. 2.不需要指出重写的方法名. 3.不要给出重写的方法的返回值类型. 4.Lambda相当于一个匿名方法 ...
- Python 中Lambda 表达式 实例解析
Lambda 表达式 lambda表达式是一种简洁格式的函数.该表达式不是正常的函数结构,而是属于表达式的类型.而且它可以调用其它函数. 1.基本格式: lambda 参数,参数...:函数功能代码 ...
- C++11 Lambda表达式简单解析
C++11 新增了非常多特性,lambda 表达式是当中之中的一个.假设你想了解的 C++11 完整特性, 建议去http://www.open-std.org/看看新标准! 非常多语言都提供了 la ...
- lambda表达式使用解析
1.Predicate/Consumer/Function/Supplier介绍 Predicate boolean test(T t); Consumer accpet(T t); Function ...
- SqlHelper简单实现(通过Expression和反射)5.Lambda表达式解析类
这个ExpressionHelper类,是整个SqlHelper中,最核心的一个类,主要功能就是将Lambda表达式转换为Sql语句.同时这个转换过程比较复杂,所以下面详细讲解一下思路和这个类的作用. ...
- python函数,lambda表达式,三目运算,列表解析,递归
一.自定义函数 定义函数时,函数体不执行:只有在调用函数时,函数体才执行.函数的结构: 1. def 2. 函数名 3. 函数体 def func_name(): 函数体 4. 返回值 如果没有声明返 ...
- 解析 Lambda 表达式
我们先创建一个表达式树: Expression<Func<int, int, int>> expression = (a,b) => a + b; 我们的例子是一个Exp ...
随机推荐
- text-overflow属性
text-overflow属性有两个值, 默认值是clip:当对象内文本溢出时不显示裁切掉. 另一个就是:ellipsis:对象内文本溢出时显示省略标记(...). 使用text-overflow:e ...
- css后续篇
5.盒模型 在css中,box model这一术语是用来设计和布局时使用的,在网页中显示一些方方正正的盒子,这种盒子就叫盒模型 盒模型有两种: 标准模型和IE模型(了解) 盒模型属性 width : ...
- 四剑客(awk)
AWK AWK简介 虽然sed编辑器是非常方便自动修改文本文件的工具,但其也有自身的限制.通常你需要一个用来处理文件中的数据的更高级工具,它能提供一个类编程环境来修改和重新组织文件中的数据.这正是ga ...
- VS各种错误集成总结,持续更新
1.error C4996: 'GetVersionExW': 被声明为已否决 解决办法:工程 -- 配置属性 --C/ C++ -- 常规 -- SDL check 关掉 2.fatal error ...
- vue 起步(一)
准备 安装nodejs(下载),Windows 安装包(.msi) npm相关 打开cmd查看npm版本, npm -v,如果没有安装npm,执行npm install npm -g进行安装 查询当前 ...
- bzoj 3450 Tyvj1952 Easy (概率dp)
3450: Tyvj1952 Easy Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下这个游戏的规则有n次点击要做,成功了就是o,失败 ...
- Navicat 12 无限期试用
最近发现navicat12又过期了,以前的是用的破解软件,然后是到1899年过期哈哈哈哈哈哈.重装了系统后,软件也重装了,发现破解软件不好使了,就先试用了,现在到期了.很是难受,这可咋整,不过在网上看 ...
- python语法基础-函数-进阶-长期维护
############### 函数的命名空间和作用域 ############## """ # 函数进阶 命名空间和作用域 命名空间 全局命名空间——我们自 ...
- Longest Increasing Subsequence (Medium)
第一次做题思路201511092250 1.采用map存储,key为nums[i],value为以nums[i]为结尾的最大递增子序列的长度 2.采用map里面的lower_bounder函数直接找出 ...
- mysql 存储过程与存储函数
第一节:存储过程和函数的引入 存储过程和函数是在数据库中定义一些SQL 语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL 语句.存储过程和函数可以避免开发人员重复的编写相同的SQL ...