带你深入JAVA8的新特性

作者: Java高级架构 | 来源:发表于2017-07-22 19:51 被阅读144次

    简介

    Oracle在2014年3月份发布了java8正式版,该版本增加了很多新特性,比如:函数式接口、lambda表达式、集合的流式操作、注解的更新、安全性增强、IO\NIO的改进

    函数式接口

    什么是函数式接口

    这是java8的一个核心概念,(Functional Interfaces).通过在接口中添加一个抽象方法,这些方法可以直接从接口中运行。我们有两种方法去实现一个函数式接口

    1. 在一个接口中定义唯一一个抽象方法,那么这个接口就成为函数式接口

    2. 通过注解@functionalInterface,用来标注这个接口是一个函数式接口。推荐这种写法,好处是如果接口不符合函数式接口的定义时,编译器会报错

    Java.lang.Runnable就是一个典型的函数式接口;

    函数式接口的用途

    主要用在Lambda表达式和方法引用上

    代码演示

    这里写图片描述

    这里写图片描述

    函数式接口的特性

    函数式接口允许定义静态方法

    函数式接口允许定义default方法

    函数式接口里允许定义java.lang.Object里的public方法

    这里写图片描述

    泛型及继承关系

    接口可以继承接口,如果一个父接口是一个函数接口,那么子接口也有可能是一个函数式接口,那么它的判断依据是什么呢?

    对于接口I, 假定M是接口成员里的所有抽象方法的继承(包括继承于父接口的方法), 除去具有和Object的public的实例方法签名的方法, 那么我们可以依据下面的条件判断一个接口是否是函数式接口, 这样可以更精确的定义函数式接口。

    如果存在一个一个方法m, 满足:

    • m的签名(subsignature)是M中每一个方法签名的子签名(signature)

    • m的返回值类型是M中的每一个方法的返回值类型的替代类型(return-type-substitutable)

    那么I就是一个函数式接口。

    情况一

    这里写图片描述

    接口Z继承了X,Y接口的m方法,由于这两个方法的签名相同,返回值也一样,所以Z有唯一的一个抽象方法int m(List arg);,可以作为函数式接口。

    情况二

    这里写图片描述

    方法签名Y.m既满足签名是X.m,并且返回值也满足,所以Z仍然是函数式接口

    情况三

    这里写图片描述

    编译出错,因为没有一个方法的签名是所有方法的子签名

    Java.util.function

    Lambda表达式在运行期间表示为一个接口函数,而接口函数只是一种只定义了一个抽象方法的接口。尽管java8里面已经有一些接口符合函数式接口的定义,比如Runnable , Comparator。但是对于我们来说显然是不够的。而如果我们需要在程序里使用非函数数接口来实现lambda表达式的操作,那么怎么去做? Java8引入了一个新增的包java.util.function, 专门用来解决这个问题。这个包里提供了很多接口

    Lambda表达式

    函数式接口的重要属性是:我们能够使用Lambda来实例化他们,Lambda表达式让你能够将函数作废方法参数,或者将代码作为数据对待。

    优点

    在java8出现之前,匿名内部类,监听器和事件处理的使用都显得很冗长,代码可读性差,而Lambda表达式的应用能够是代码变得更加紧凑,可读性增强

    语法

    Lambda表达式由三个部分组成:

    第一部分:一个括号内用逗号分割形式参数,参数是函数式接口里面方法的参数

    第二部分:一个箭头号 ->

    第三部分:方法体,可以是表达式和代码块

    情况一

    方法体为表达式,则该表达式的值作为返回值返回:

    情况二

    方法体为代码块,必须要用{}包裹起来,如果该接口有返回值,则需要return返回值,反之则不需要

    这里写图片描述

    代码演示

    情况1, 对内部类进行简化

    这里写图片描述

    情况2,我们用list排序来演示效果

    这里写图片描述

    大家可以点击加入群:606187239【JAVA大牛交流学习】

    里面有Java高级大牛直播讲解知识点 走的就是高端路线 (如果你想跳槽换工作 但是技术又不够 或者工作上遇到了瓶颈 我这里有一个JAVA的免费直播课程 讲的是高端的知识点基础不好的误入哟 只要你有1-5年的开发经验可以加群找我要课堂链接 注意:是免费的 没有开发经验误入哦)

    简化处理后

    这里写图片描述

    方法引用

    有时候Lambda表达式的代码只是一个简单的方法调用而已,而遇到另外一种情况我们可以更进一步去简化,我们称之为方法引用;

    引用静态方法

    引用对象的实例方法

    引用某个类型的任意对象的实例方法

    引用类构造函数

    代码演示

    我们同样针对一个数组进行排序,综合以上所有提到的方法引用类型

    第一步

    第二步

    第三步

    集合流式操作

    Java8引入了流式操作(Stream),通过该操作可以实现对集合的并行处理和函数式操作。

    1. 根据操作返回的结果不同,流式操作又分为中间操作和最终操作。最终操作返回的是一个特定类型的结果;而中间操作返回的是流本身,因此就可以将多个操作一次串联起来;

    2. 根据流的并发性、又可以分为串行和并行两种,流式操作实现了对集合的过滤、排序、映射等功能

    串行流和并行流

    通过串行流操作是在一个线程中依次完成,而并行流则是在多个线程上同时执行。并行和串行的流操作可以相互切换:通过

    Stream.sequential()返回串行流

    Stream.parallel() 返回并行流

    相比于串行流,并行流可以很大程度上提高程序的执行效率

    串行/并行排序演示

    中间操作

    该操作会保持 stream 处于中间状态,允许做进一步的操作。它返回的还是的 Stream,允许更多的链式操作。常见的中间操作有:

    filter():对元素进行过滤;

    sorted():对元素排序;

    map():元素的映射;

    distinct():去除重复元素;

    subStream():获取子 Stream 等。

    终止操作

    该操作必须是流的最后一个操作,一旦被调用,Stream 就到了一个终止状态,该操作之后不能再链式的添加其他操作。常见的终止操作有:

    forEach():对每个元素做处理;

    toArray():把元素导出到数组;

    findFirst():返回第一个匹配的元素;

    anyMatch():是否有匹配的元素等。

    相关文章

      网友评论

        本文标题:带你深入JAVA8的新特性

        本文链接:https://www.haomeiwen.com/subject/xjnukxtx.html