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. 文件&报表状态ID

    def_filestatus Uploading=4 WaitingParse=6 Parsing=10 Completed=14 ParseError=1006 UploadError=1004 d ...

  2. Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】

    前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就 ...

  3. 028_rync和inotify实现实时备份

    一.服务节点安装inotify-tools. 确保系统后以下输出=> [root@xxxx]# ll /proc/sys/fs/inotify/ total 0 -rw-r--r-- 1 roo ...

  4. Unicode范围预览

    链接: https://www.zhangxinxu.com/study/201611/show-character-by-charcode.php?range=4E00-9FBB 备注: Unico ...

  5. LeetCode(57):插入区间

    Hard! 题目描述: 给出一个无重叠的 ,按照区间起始端点排序的区间列表. 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间). 示例 1: 输入: i ...

  6. wpf Assembly.LoadFile dll GetType 反射 抛异常 不具有由 URI 识别的资源。

    public static void LoadViewFromUri(this Window window, string baseUri) { try { var resourceLocater = ...

  7. laravel 列表搜索查询(when,with用法以及关联图像id处理图像路径)

    laravel中比较常规的列表查询: /** * 活动列表 * @param Request $request * @return \Illuminate\Http\JsonResponse */ p ...

  8. PHP实现删除字符串中任何字符的函数

    function delStr($start, $end, $orgenStr) { //读取要删除字符位置的前一部分字符串,并赋值给$temp //strpos读取字符第一次出现的位置 //subs ...

  9. BZOJ1925 [Sdoi2010]地精部落 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1925 题意概括 给出n,n<=4200,问1~n这些数的排列中,有多少满足一下性质: 性质: ...

  10. 第二章HTML,JavaScript简介

    概念: URL:网上标准资源的地址. HTTP协议:客户端发出请求和得到回应的标准协议. HTML:超文本标记语言.是网络上的通用语言,也是网络web语言基础. 2.1服务器与浏览器 举个例子:A同学 ...