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. 腾讯云YUM安装失效

    修改路由后,YUM安装失效,提示不能解析YUM源 yum clear chche yum makecache

  2. How to scroll down with Phantomjs to load dynamic content

    page.open('http://example.com/?q=houston', function () { // Checks for bottom div and scrolls down f ...

  3. C:malloc/calloc/realloc/alloca内存分配函数

    原文地址:http://www.cnblogs.com/3me-linux/p/3962152.html calloc(), malloc(), realloc(), free(),alloca() ...

  4. HDU 3579

    标准同余方程组,只是在求出值后如果为0,应该输出Mi的Lcm: #include<iostream> #include<cstdio> #include<cstring& ...

  5. PHP 将数组的值赋值给一组变量

    经常需要将一个字符串分割成一组值,然后赋值给不同的变量. 逐行赋值非常繁琐,于是查了一下 PHP 中是否有类似 python 中 a, b = (a, b) 的操作. 果然有 $info = arra ...

  6. 【HTTP】 Fiddler简介

    1.为什么是Fiddler? 抓包工具有很多,小到最常用的web调试工具firebug,达到通用的强大的抓包工具wireshark.为什么使用fiddler?原因如下: a.Firebug虽然可以抓包 ...

  7. 你可能不知道的git clean

    git clean是干啥的? git clean可以帮你清理workspace中未被git版本控制的文件,比如临时文件,构建出来的二进制文件. 使用方法 如果你的clean.requireForce项 ...

  8. python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)

    一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 from app01 import views urlpatterns = [ path('admin/', admi ...

  9. python 全栈开发,Day57(响应式页面-@media介绍,jQuery补充,移动端单位介绍,Bootstrap学习)

    昨日内容回顾 ajax //get post 两种方式 做 请求 get 主要是获取数据 post 提交数据 同一个路由地址 既可以是get请求也可以是post请求 一个路由对应一个函数 get请求 ...

  10. centos7 下安装配置python3.6

    一.首先,官网下载python3的所需版本. wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz 二.然后,解压缩文件> ...