我是靠谱客的博主 俏皮棒棒糖,最近开发中收集的这篇文章主要介绍JAVA8新特性 ------- Lamda表达式的运用Lambda语法详解Lambda表达式眼中的外部世界方法引用(Method reference)和构造器引用(construct reference),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

第一、了解什么是lambda 表达式

  “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

   说白了Lamda就是一个函数表达式(学过C++和js的应该都很明白了),我们就可以衍生到函数式编程了,也就是在java中把函数作为了一等公民

第二、为什么要用Lamda表达式

1.它简化了我们编码过程

2.“lambda 表达式”是一段可以传递的代码,因此它可以被执行一次或多次(什么意思呢,就是lambda表达式只需要我们传递参数和实现过程,它会自动根据上下文来匹配计算结果值

第三、我们怎么彻底的学习Lamda表达式

1.语法

Lambda语法详解

我们在此抽象一下lambda表达式的一般语法:

(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}

从lambda表达式的一般语法可以看出来,还是挺符合上面给出的非精确版本的定义–“一段带有输入参数的可执行语句块”。

上面的lambda表达式语法可以认为是最全的版本,写起来还是稍稍有些繁琐。别着急,下面陆续介绍一下lambda表达式的各种简化版:

1. 参数类型省略–绝大多数情况,编译器都可以从上下文环境中推断出lambda表达式的参数类型。这样lambda表达式就变成了:

(param1,param2, ..., paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}

所以我们最开始的例子就变成了(省略了List的创建):

List<String> lowercaseNames = names.stream().map((name) -> {return name.toLowerCase();}).collect(Collectors.toList());

2. 当lambda表达式的参数个数只有一个,可以省略小括号。lambda表达式简写为:

param1 -> {
statment1;
statment2;
//.............
return statmentM;
}

所以最开始的例子再次简化为:

List<String> lowercaseNames = names.stream().map(name -> {return name.toLowerCase();}).collect(Collectors.toList());

3. 当lambda表达式只包含一条语句时,可以省略大括号、return和语句结尾的分号。lambda表达式简化为:

param1 -> statment

所以最开始的例子再次简化为:

List<String> lowercaseNames = names.stream().map(name -> name.toLowerCase()).collect(Collectors.toList());

4. 使用Method Reference(具体语法后面介绍)

//注意,这段代码在Idea 13.0.2中显示有错误,但是可以正常运行
List<String> lowercaseNames = names.stream().map(String::toLowerCase).collect(Collectors.toList());

第二、实例

Lambda表达式眼中的外部世界

我们前面所有的介绍,感觉上lambda表达式像一个闭关锁国的家伙,可以访问给它传递的参数,也能自己内部定义变量。但是却从来没看到其访问它外部的变量。是不是lambda表达式不能访问其外部变量?我们可以这样想:lambda表达式其实是快速创建SAM接口的语法糖,原先的SAM接口都可以访问接口外部变量,lambda表达式肯定也是可以(不但可以,在java8中还做了一个小小的升级,后面会介绍)。

String[] array = {"a", "b", "c"};
for(Integer i : Lists.newArrayList(1,2,3)){
Stream.of(array).map(item -> Strings.padEnd(item, i, '@')).forEach(System.out::println);
}

上面的这个例子中,map中的lambda表达式访问外部变量Integer i。并且可以访问外部变量是lambda表达式的一个重要特性,这样我们可以看出来lambda表达式的三个重要组成部分:

  • 输入参数
  • 可执行语句
  • 存放外部变量的空间

不过lambda表达式访问外部变量有一个非常重要的限制:变量不可变(只是引用不可变,而不是真正的不可变)。

String[] array = {"a", "b", "c"};
for(int i = 1; i<4; i++){
Stream.of(array).map(item -> Strings.padEnd(item, i, '@')).forEach(System.out::println);
}

上面的代码,会报编译错误。因为变量i被lambda表达式引用,所以编译器会隐式的把其当成final来处理(ps:大家可以想象问什么上一个例子不报错,而这个报错。)细心的读者肯定会发现不对啊,以前java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。Bingo,在java8对这个限制做了优化(前面说的小小优化),可以不用显示使用final修饰,但是编译器隐式当成final来处理。

lambda眼中的this

在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。

方法引用(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的下划线语法更加通用。比较才能看出,翠花,上代码!

List<String> names = new ArrayList<>();
names.add("TaoBao");
names.add("ZhiFuBao");
names.stream().map(name -> name.charAt(0)).collect(Collectors.toList());

上面的这段代码就是给定一个String类型的List,获取每个String的首字母,并将其组合成新的List。这段代码就没办法使用方法引用来简化。接下来,我们简单对比一下Scala的下划线语法(不必太纠结Scala的语法,这里只是做个对比):

//省略List的初始化
List[String] names = ....
names.map(_.charAt(0))

在Scala中基本不用写lambda表达式的参数声明。


最后

以上就是俏皮棒棒糖为你收集整理的JAVA8新特性 ------- Lamda表达式的运用Lambda语法详解Lambda表达式眼中的外部世界方法引用(Method reference)和构造器引用(construct reference)的全部内容,希望文章能够帮你解决JAVA8新特性 ------- Lamda表达式的运用Lambda语法详解Lambda表达式眼中的外部世界方法引用(Method reference)和构造器引用(construct reference)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部