JAVA 新特性:lambda表达式
2016-10-04 12:38
686 查看
本系列(java 8新特性)都是整理其他博客而来
相关文章:
1.Lambda表达式
http://blog.csdn.net/youyou1543724847/article/details/52733395
2.流
http://blog.csdn.net/youyou1543724847/article/details/52733477
3.函数式接口
http://blog.csdn.net/youyou1543724847/article/details/52733660
4.接口新特性
http://blog.csdn.net/youyou1543724847/article/details/52733675
目录:
1.Lambda表达式
2.函数式接口
3.接口新特性
简单点说就是:一个不用被绑定到一个标识符上,并且可能被调用的函数。这个解释还不够通俗,lambda表达式可以这样定义(不精确,自己的理解):一段带有输入参数的可执行语句块。这样就比较好理解了吧?一例胜千言。有读者反馈:不理解Stream的含义,所以这里先提供一个没用stream的lambda表达式的例子。
看一个简单的例子:
从lambda表达式的一般语法可以看出来,还是挺符合上面给出的非精确版本的定义–“一段带有输入参数的可执行语句块”。
上面的lambda表达式语法可以认为是最全的版本,写起来还是稍稍有些繁琐。别着急,下面陆续介绍一下lambda表达式的各种简化版:
1. 参数类型省略–绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型。这样lambda表达式就变成了:
所以我们最开始的例子就变成了(省略了List的创建):
List lowercaseNames = names.stream().map((name) -> {return name.toLowerCase();}).collect(Collectors.toList());
2. 当lambda表达式的参数个数只有一个,可以省略小括号。lambda表达式简写为:
所以最开始的例子再次简化为:
List lowercaseNames = names.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());
3. 当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。lambda表达式简化为:
param1 -> statment
所以最开始的例子再次简化为:List lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());
4. 使用Method Reference(具体语法后面介绍)
上面的这个例子中,map中的lambda表达式访问外部变量Integer i。并且可以访问外部变量是lambda表达式的一个重要特性,这样我们可以看出来lambda表达式的三个重要组成部分:
输入参数
可执行语句
存放外部变量的空间
不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。
objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。
最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。
吐槽一下方法引用
表面上看起来方法引用和构造器引用进一步简化了lambda表达式的书写,但是个人觉得这方面没有Scala的下划线语法更加通用。比较才能看出,翠花,上代码!
相关文章:
1.Lambda表达式
http://blog.csdn.net/youyou1543724847/article/details/52733395
2.流
http://blog.csdn.net/youyou1543724847/article/details/52733477
3.函数式接口
http://blog.csdn.net/youyou1543724847/article/details/52733660
4.接口新特性
http://blog.csdn.net/youyou1543724847/article/details/52733675
目录:
1.Lambda表达式
2.函数式接口
3.接口新特性
Lambda表达式
什么是Lambda表达式
定义:a function (or a subroutine) defined, and possibly called, without being bound to an identifier简单点说就是:一个不用被绑定到一个标识符上,并且可能被调用的函数。这个解释还不够通俗,lambda表达式可以这样定义(不精确,自己的理解):一段带有输入参数的可执行语句块。这样就比较好理解了吧?一例胜千言。有读者反馈:不理解Stream的含义,所以这里先提供一个没用stream的lambda表达式的例子。
看一个简单的例子:
语法
(type1 param1,type2 param2,.... . typeN paramN) -> { statement1; statement2; .... return statementM; }
从lambda表达式的一般语法可以看出来,还是挺符合上面给出的非精确版本的定义–“一段带有输入参数的可执行语句块”。
上面的lambda表达式语法可以认为是最全的版本,写起来还是稍稍有些繁琐。别着急,下面陆续介绍一下lambda表达式的各种简化版:
1. 参数类型省略–绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型。这样lambda表达式就变成了:
(param1,param2,.....paramN) -> { statement1; statement2; .... return statementM; }
所以我们最开始的例子就变成了(省略了List的创建):
List lowercaseNames = names.stream().map((name) -> {return name.toLowerCase();}).collect(Collectors.toList());
2. 当lambda表达式的参数个数只有一个,可以省略小括号。lambda表达式简写为:
param1 -> { statement1; statement2; .... return statementM; }
所以最开始的例子再次简化为:
List lowercaseNames = names.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());
3. 当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。lambda表达式简化为:
param1 -> statment
所以最开始的例子再次简化为:List lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());
4. 使用Method Reference(具体语法后面介绍)
Lambda表达式眼中的外部世界
我们前面所有的介绍,感觉上lambda表达式像一个闭关锁国的家伙,可以访问给它传递的参数,也能自己内部定义变量。但是却从来没看到其访问它外部的变量。是不是lambda表达式不能访问其外部变量?我们可以这样想:lambda表达式其实是快速创建SAM接口的语法糖,原先的SAM接口都可以访问接口外部变量,lambda表达式肯定也是可以(不但可以,在java8中还做了一个小小的升级,后面会介绍)。上面的这个例子中,map中的lambda表达式访问外部变量Integer i。并且可以访问外部变量是lambda表达式的一个重要特性,这样我们可以看出来lambda表达式的三个重要组成部分:
输入参数
可执行语句
存放外部变量的空间
不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。
方法引用(Method reference)和构造器引用(construct reference)
方法引用
前面介绍lambda表达式简化的时候,已经看过方法引用的身影了。方法引用可以在某些条件成立的情况下,更加简化lambda表达式的声明。方法引用语法格式有以下三种:objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
前两种方式类似,等同于把lambda表达式的参数直接当成instanceMethod|staticMethod的参数来调用。比如System.out::println等同于x->System.out.println(x);Math::max等同于(x, y)->Math.max(x,y)。
最后一种方式,等同于把lambda表达式的第一个参数当成instanceMethod的目标对象,其他剩余参数当成该方法的参数。比如String::toLowerCase等同于x->x.toLowerCase()。
构造器引用
构造器引用语法如下:ClassName::new,把lambda表达式的参数当成ClassName构造器的参数 。例如BigDecimal::new等同于x->new BigDecimal(x)。吐槽一下方法引用
表面上看起来方法引用和构造器引用进一步简化了lambda表达式的书写,但是个人觉得这方面没有Scala的下划线语法更加通用。比较才能看出,翠花,上代码!
原理:
Java 7引入了invokedynamic指令,它是一个JVM指令,允许动态语言在run-time时动态绑定。Java 8的Lambda表达式并不是匿名类的语法糖,它不会在编译的时候生成类似于匿名类的xxx1.class,而是在运行的时候使用invokeDynamic指令。对于一条Lambda表达式在class里边会包含一个invokedynamic命令和一个静态方法。运行时会使用LambdaMetafactory#metafactory做成一个Lambda1的内部类再调用该函数式接口的实例。在运行时生成class,就是避免class太多影响加载速度,像Stream那样的到处是Lambda。相关文章推荐
- Java 8新特性:lambda表达式
- Java 8新特性-3 Lambda 表达式
- JAVA8新特性(Lambda 表达式)
- Java 8新特性:新语法方法引用和Lambda表达式及全新的Stream API
- Java8新特性之Lambda表达式
- Java 8新特性:lambda表达式(四)转载总结
- Android Studio使用gradle-retrolambda支持Java8 新特性 Lambde表达式
- Java8特性详解 lambda表达式 Stream
- java8新特性之lambda表达式(一)
- Java 8新特性:新语法方法引用和Lambda表达式及全新的Stream API
- java8新增特性(一)---Lambda表达式
- Java8 新特性----函数式接口,以及和Lambda表达式的关系
- Java 8 新特性:Lambda 表达式
- Java8 新特性之 Lambda 表达式
- Java8新特性——lambda表达式
- Java8新特性 - Lambda表达式 - 基本知识
- JAVA 1.8 新特性学习(2) lambda表达式
- Java 8 新特性:Lambda 表达式之方法引用(Lambda 表达式补充版)
- java8新特性学习笔记(一) Lambda表达式
- Java8 新特性之一---------Lambda表达式和函数式接口