Major Marquis Warren 沃伦·马奎斯少校

“Tring to get a couple of bounties in to Red Rock.”我想带几个通缉犯去红石镇

一、基本介绍

  我的理解里,新特性中的lambda就是提供了Java的语句优化(读写起来更简单)的功能。如果你想让你的代码更短,更精简,lambda给你的舞台无限大。

  看一下官方的给lambda的定义“a function (or a subroutine) defined, and possibly called, without being bound to an identifier。” ——可以调用的匿名函数

  首先先了解一个新的概念:Java 8 引入的一个核心概念是函数式接口。如果一个接口定义个唯一一个抽象方法,那么这个接口就成为函数式接口(理解起来像虽然说继承了一个接口,但实际上只会实现一个函数,所以叫函数式接口)。比如,java.lang.Runnable就是一个函数式接口,因为它只顶一个一个抽象方法: public abstract void run();同时,引入了一个新的Annotation:@FunctionalInterface。可以把他它放在一个接口前,表示这个接口是一个函数式接口。加上它的接口不会被编译,除非你设法把它变成一个函数式接口。它有点像@Override,都是声明了一种使用意图,避免你把它用错。

  已经明白了函数式接口的概念下,我们来看一下lambda在函数式接口使用的时候有什么样的变化,下面例子中前两个

//常见的多线程方法实现Runnable接口,先实现然后new一个线程start起来。

class myThread implements Runnable{      //创建线程类

public void run(){

System.out.println(“Thread body”);

}

}

new Thread(new myThread()).start();//开启线程

//使用匿名函数新建线程类

Thread td = new Thead(new Runnable(){

   @Override public void run(){

     System.out.print("Thread body");

   }

}
td.start();

//lambda写法

Thread td =new Thread(()->System.out.println("Thread body"));

td.start();

我们单独的看一下最后的lambda写法,因为函数式接口实现的时候只有一个方法进行实现,所以lambda精简到了你只需要给这个new Thread()一个匿名函数作为参数的写法。其中()->System.out.println("Thread body")就是一个lambda表达式匿名函数。不理解没有关系,我们往下看

二、lambda语法详解

  先来个抽象的表达式,括号中作为参数。表达式使用大括号包起来,最后return一个值。中间使用->链接

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

  

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

(Type1 param1, Type2 param2, ..., TypeN paramN) -> { //省略了参数类型
statment1;
statment2;
//.............
return statmentM;
}
 

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

param1 -> { //省略了括号
statment1;
statment2;
//.............
return statmentM;
}
 

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

param1 ->statment //省略了大括号

  

我们再来看一下上边讲多线程实现的例子:()->System.out.println("Thread body")。此处没有参数,所以只有了两个圆括号做为输入,因为只有一行语句,省略了大括号。

三、lambda表达式的访问权限

  lambda作为一匿名函数,可以访问传递给他的参数,可以定义自己的变量(在自己的表达式中)。那么它可以访问外部的变量吗(像一个正常函数访问)?,答案是肯定的。

  但是有一点与普通函数访问不同。所有被访问的外部变量都不可以改变(只是引用不可变,而不是真正的不可变)。以前java的匿名内部类在访问外部变量的时候,外部变量必须用final修饰。在java8对这个限制做了优化(前面说的小小优化),可以不用显示使用final修饰,但是编译器隐式当成final来处理。

四、方法引用和构造器引用(Method reference,construct reference)

有时,我们需要执行的代码在某些类中已经存在,这时我们没必要再去写Lambda表达式,可以直接使用该方法,这种情况我们称之为方法引用,如下所示,未采用方法引用前的代码

如下所示 //这里有Stream的操作,在下篇文章中会有介绍

Stream.of(datas).forEach(param -> {System.out.println(param);});

使用方法引用后的代码如下所示

Stream.of(datas).forEach(System.out::println);

以上示例使用的是out对象,下面示例使用的是类的静态方法引用对字符串数组里的元素忽略大小写进行排序

String []datas = new String[] {"peng","Zhao","li"};
Arrays.sort(datas,String::compareToIgnoreCase);
Stream.of(datas).forEach(System.out::println);

上面就是方法引用的一些典型示例

方法引用的具体分类

Object:instanceMethod
Class:staticMethod
Class:instanceMethod

上面分类中前两种在Lambda表达式的意义上等同,都是将参数传递给方法,如上示例

System.out::println == x -> System.out.println(x)

最后一种分类,第一个参数是方法执行的目标,如下示例

String::compareToIgnoreCase == (x,y) ->     x.compareToIgnoreCase(y)

还有类似于super::instanceMethod这种方法引用本质上与Object::instanceMethod类似

构造方法引用与方法引用类似,除了一点,就是构造方法引用的方法是new以下是两个示例

示例一:

String str = "test";
Stream.of(str).map(String::new).peek(System.out::println).findFirst();

示例二:(此处的stream是1.8的另一个新特性,下篇文章有介绍)

String []copyDatas = Stream.of(datas).toArray(String[]::new);
Stream.of(copyDatas).forEach(x -> System.out.println(x));

总结一下,构造方法引用有两种形式

Class::new
Class[]::new

参考链接

http://ifeve.com/lambda/

https://www.cnblogs.com/figure9/archive/2014/10/24/4048421.html

图片来源:八恶人(movie)

Java 8新特性之lambda(八恶人-2)的更多相关文章

  1. Java 8新特性探究(八)精简的JRE详解

    http://www.importnew.com/14926.html     首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 Java小组 工具资源 - 导航条 - 首页 所有文章 资讯 ...

  2. [转帖]Java 8新特性探究(八)精简的JRE详解

    Java 8新特性探究(八)精简的JRE详解 https://my.oschina.net/benhaile/blog/211804 精简版的api   撸了今年阿里.网易和美团的面试,我有一个重要发 ...

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

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

  4. Java 8新特性(Lambda,Stream API)

    由于最近总监要求学习Java 8的一些知识,就去网上找了 一套教程来学习学习,将学习结果做一个小的总结记录,方便以后使用: 1.Java 8的优点 2.Lambda表达式优点 2.1Lambda实例 ...

  5. [转]Java 8新特性探究(lambda)

    原文地址:http://my.oschina.net/benhaile/blog/175012 目录[-] 函数式接口 Lambda语法 方法引用 总结 函数式接口 函数式接口(functional ...

  6. Java 8新特性-3 Lambda 表达式

    在 Java 8 之前,匿名内部类,监听器和事件处理器的使用都显得很冗长,代码可读性很差. 在Java 8 之前使用匿名内部类: 例如 interface ITestPrint{ public voi ...

  7. Java 8 新特性之 Lambda表达式

    Lambda的出现就是为了增强Java面向过程编程的深度和灵活性.今天就来分享一下在Java中经常使用到的几个示例,通过对比分析,效果应该会更好. – 1.实现Runnable线程案例 其存在的意义就 ...

  8. Java 8 新特性-菜鸟教程 (1) -Java 8 Lambda 表达式

    Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表达式可以使代码变的更加 ...

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

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

随机推荐

  1. linux系统分析工具续-SystemTap和火焰图(Flame Graph)

    本文为网上各位大神文章的综合简单实践篇,参考文章较多,有些总结性东西,自认暂无法详细写出,建议读文中列出的参考文档,相信会受益颇多.下面开始吧(本文出自 “cclo的博客” 博客,请务必保留此出处ht ...

  2. struts2_maven_learning

    以下为学习maven struts2 的学习过程,现记录如下. 1.创建一个完善的maven程序 maven:(jar) 1)maven project 2)facet 3)pom.xml,depen ...

  3. day 11 前方高能-迭代器

    第一类对象 -----函数名  == 变量名 函数对象可以像变量一样进行赋值 还可以作为列表的元素进行使用 可以作为返回值返回 def wrapper():     def inner():      ...

  4. 大数据入门第十八天——kafka整合flume、storm

    一.实时业务指标分析 1.业务 业务: 订单系统---->MQ---->Kakfa--->Storm 数据:订单编号.订单时间.支付编号.支付时间.商品编号.商家名称.商品价格.优惠 ...

  5. Exp1 PC平台逆向破解(5)M

    Exp1 PC平台逆向破解(5)M [ 直接修改程序机器指令,改变程序执行流程] 用命令cp pwn1 20155320备份pwn1 输入objdump -d 20155320反汇编,找到call指令 ...

  6. 20155330 《网络对抗》 Exp2 后门原理与实践

    20155330 <网络对抗> 实验二 后门原理与实践 基础问题回答 例举你能想到的一个后门进入到你系统中的可能方式? 在网站上下载非官方软件,所下载的软件中携带伪装过的后门程序. 例举你 ...

  7. Java实现Zip压缩包解压

        对zip压缩包的解压是比较常见的应用场景,java代码的实现也很简单.废话不多说,直接上代码吧 一.代码 /** * zip解压 * @param srcFile zip源文件 * @para ...

  8. POJ2531&&1416&&2676&&1129

    搜索专题的最后一块了,也告别了这些老的东西了 接下来就是些全新的内容了啊! 这次的标签是简单搜索技巧和剪枝,也就是优化爆搜 当然,像Dancing links这样的玄学操作还是没有的 2531 题意: ...

  9. 汇编 LEA 指令

    知识点:  LEA指令  &与LEA  OD里修改汇编代码 一.LEA指令格式 有效地址传送指令 LEA 格式: LEA 操作数A, 操作数B 功能: 将操作数B的有效地址传送到指定的的 ...

  10. Spring学习(十九)----- Spring与WEB容器整合

    首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 filter 写在 listener 的前面而会先加载 filter.最终得出的结论是:listener -> ...