Lambda

一、如何辨别Lambda表达式

 Runnable noArguments = () -> System.out.println("Hello World"); 

 ActionListener oneArgument = event -> System.out.println("button clicked");
 Runnable multiStatement = () -> {
     System.out.print("Hello");
     System.out.println(" World");
 };

 BinaryOperator<Long> add = (x, y) -> x + y; 

 BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y; 

1)没有参数用空“()”表示。

2)只有一个参数,括号可以省略,只写参数名。

3)Lambda 表达式的主体不仅可以是一个表达式, 而且也可以是一段代码块, 使用大括号
( {}) 将代码块括起来。 该代码块和普通方法遵循的规则别无二致,可以用返
回或抛出异常来退出。 只有一行代码的 Lambda 表达式也可使用大括号, 用以明确 Lambda
表达式从何处开始、 到哪里结束。

4)Lambda 表达式也可以表示包含多个参数的方法。 这时就有必要思考怎样去阅
读该 Lambda 表达式。 这行代码并不是将两个数字相加, 而是创建了一个函数, 用来计算
两个数字相加的结果。 变量 add 的类型是 BinaryOperator<Long>, 它不是两个数字的和,
而是将两个数字相加的那行代码。括号中的参数就可以有注解和final。

5)到目前为止, 所有 Lambda 表达式中的参数类型都是由编译器推断得出的。 这当然不错,
但有时最好也可以显式声明参数类型, 此时就需要使用小括号将参数括起来, 多个参数的
情况也是如此。

6)方法/构造器引用:Lambda表达式调用参数的一种简便写法。

三种写法:

对象::实例方法

类::静态方法

类::实例方法

第三种情况,第一个参数会成为执行方法的对象

this::实例方法

super::实例方法

闭合类.this:方法

如:

artist -> artist.getName()
//可以写成
Artist :: getName
 button.setOnAction(event -> System.out.println(event));
 //可以写成
 button.setOnAction(System.out::println());

构造函数有同样的写法:

(name, nationality)-> new Artist(name, nationlity)
//可以写为
Artist :: new  

也可以有数组构造器引用:

 int[]::new //等同于x -> new int[x]

7)目标类型是指 Lambda 表达式所在上下文环境的类型。 比如, 将 Lambda 表
达式赋值给一个局部变量, 或传递给一个方法作为参数, 局部变量或方法参
数的类型就是 Lambda 表达式的目标类型。

二、引用值,而不是变量

匿名内部类需要引用它所在方法里的变量时(局部变量),需要将变量声明为final。

Java 8中放松了这一限制,可以引用非final变量,但该变量在既成事实上必须是final(只能给该变量赋值一次,

如果试图给该变量多次赋值,然后在Lambda表达式中引用它,编译器就会报错)。

这种行为也解释了为什么lamdba表达式为闭包-------含有自由变量(不是传入参数,且没有在方法块中定义的变量)的代码块。

变量的值:除了基础类型外,变量的值指的是它的引用(地址)。 例如:

String msg = "hello world";
msg = "good morning";
executor.submit(()->System.out.println(msg));

这么做的原因与匿名内部类类似。

三、函数接口

函数接口是只有一个抽象方法的接口,用作lambda表达式的类型。

四、类型推断

可省略Lambda表达式中所有参数的类型。

无法推断出类型的报错信息:

 Operator '& #x002B;' cannot be applied to java.lang.Object, java.lang.Object.

五、重载和继承

1.重载

1)Lambda 表达式作为参数时,其类型由它的目标类型推导得出, 推导过程遵循
如下规则:
1.如果只有一个可能的目标类型, 由相应函数接口里的参数类型推导得出;
2.如果有多个可能的目标类型, 由最具体的类型推导得出;
3.如果有多个可能的目标类型且最具体的类型不明确, 则需人为指定类型。

2)每个用作函数接口的接口都应该添加@FunctionalInterface注释,该注释会检查被注释接口是否符合函数接口的标准。

2.继承

1)默认方法

引入默认方法目的:接口的向后兼容(如果没有默认方法,我们在接口中定义一个新方法时......)。

1.无论函数接口,还是非函数接口都可以使用默认方法。

2.任何时候,默认方法与类中的方法产生冲突,优先选择类中的方法。

3.多重继承,类实现的多个接口中有方法签名相同的默认方法,此时编译器会报错:

 class Musical Carriage
 inherits unrelated defaults for rock() from types Carriage and Jukebox。

解决方法:重写:

 public class MusicalCarriage
 implements Carriage, Jukebox {
 @Override
 public String rock() {
 return Carriage.super.rock();
 }
 }

六、与抽象类的区别

接口和抽象类之间还是存在明显的区别。 接口允许多重继承, 却没有成员变量; 抽象类可
以继承成员变量, 却不能多重继承。

七、接口的静态方法

在Java8中你可以为接口添加静态方法。

如果一个方法有充分的语义原因和某个概念相关, 那么就应该将该方法和相关的类
或接口放在一起, 而不是放到另一个工具类中。 这有助于更好地组织代码, 阅读代码的人
也更容易找到相关方法。

Java 8新特性----Lambda的更多相关文章

  1. Java 8 新特性 - Lambda表达式

    Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...

  2. 浅析Java 8新特性Lambda Expression

    什么是Lambda Expression 对于Lambda Expression,我的理解是,它是一个函数表达式,如下: (int x, int y) -> x - y 符号左边定义了函数的输入 ...

  3. Java 8新特性--Lambda表达式作为返回值

    lambda表达式作为方法的返回值:

  4. Java 8 新特性--Lambda表达式作为方法参数

    Lambda表达式的使用场景: 当方法的参数是一个函数式接口时,可以使用Lambda表达式进行简化—— 首先,前提是Runnable接口是一个函数式接口,经过查看源码得知,确实如此: 将Runnabl ...

  5. Java 12 新特性介绍,快来补一补

    Java 12 早在 2019 年 3 月 19 日发布,它不是一个长久支持(LTS)版本.在这之前我们已经介绍过其他版本的新特性,如果需要可以点击下面的链接进行阅读. Java 11 新特性介绍 J ...

  6. Java 8 新特性:Lambda、Stream和日期处理

    1. Lambda 简介   Lambda表达式(Lambda Expression)是匿名函数,Lambda表达式基于数学中的λ演算得名,对应于其中的Lambda抽象(Lambda Abstract ...

  7. Spring 4支持的Java 8新特性一览

    有众多新特性和函数库的Java 8发布之后,Spring 4.x已经支持其中的大部分.有些Java 8的新特性对Spring无影响,可以直接使用,但另有些新特性需要Spring的支持.本文将带您浏览S ...

  8. Java 8 新特性终极版

    声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己 ...

  9. Java 8新特性前瞻

    快端午小长假了,要上线的项目差不多完结了,终于有时间可以坐下来写篇博客了. 这是篇对我看到的java 8新特性的一些总结,也是自己学习过程的总结. 几乎可以说java 8是目前为止,自2004年jav ...

随机推荐

  1. Linux串口—struct termios结构体【转】

    转自:https://blog.csdn.net/yemingzhu163/article/details/5897156 一.数据成员 termios 函数族提供了一个常规的终端接口,用于控制非同步 ...

  2. V4L2文档翻译(一)【转】

    转自:https://blog.csdn.net/airk000/article/details/23218903 相关资料 https://www.kernel.org/doc/Documentat ...

  3. Linux系统编程【转】

    转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...

  4. 命令行command line 使用 http proxy的设置方法 Setting Up HTTP Proxy in Terminal

    Step 1: Install Shadowsocks Client Shadowsocks is an open-source proxy project to help people visit ...

  5. python2.7源码或第三方包里埋藏的坑(持续更新)

    1.psutil包,aix环境下,如果进程命令过长的话,程序无法取得完整的进程命令,测试代码如下 import psutil proc=psutil.Process(11534558) pidDict ...

  6. C++:__stdcall详解

    原文地址:http://www.cnblogs.com/songfeixiang/p/3733661.html 对_stdcall 的理解(上)在C语言中,假设我们有这样的一个函数:int funct ...

  7. Ex 5_33 实现一个关于公式长度(其中所有文字总的出现次数)为线性时间的Horn公式可满足性问题_第十次作业

    对于所有的蕴含式,生成一张有向图,对于每一个蕴含式,将左边的每一个文字连接到一个中间结点,并用中间结点记录蕴含式左边文字的数量,然后将中间结点连接到蕴含式的右侧结点.例如,对于蕴含式集合 生成的有向图 ...

  8. 通用jsonp跨域技术获取天气数据

    1. 前言 在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题可以使用jsonp技术 2.代码 <!DOCT ...

  9. linux压缩与解压

    1.tar -zcvf /home/aaa.tar.gz /xahot tar -zcvf 打包后生成的文件名全路径 要打包的目录 解压 #tar -zxvf /usr/local/test.tar. ...

  10. java :: Java中的双冒号操作符

    java中的双冒号操作符 定义 双冒号运算操作符是类方法的句柄,lambda表达式的一种简写,这种简写的学名叫eta-conversion或者叫η-conversion. 通常的情况下: 把 x -& ...