Java 8 新特性概述.docx

上传人:b****0 文档编号:17544104 上传时间:2023-07-26 格式:DOCX 页数:17 大小:204.56KB
下载 相关 举报
Java 8 新特性概述.docx_第1页
第1页 / 共17页
Java 8 新特性概述.docx_第2页
第2页 / 共17页
Java 8 新特性概述.docx_第3页
第3页 / 共17页
Java 8 新特性概述.docx_第4页
第4页 / 共17页
Java 8 新特性概述.docx_第5页
第5页 / 共17页
Java 8 新特性概述.docx_第6页
第6页 / 共17页
Java 8 新特性概述.docx_第7页
第7页 / 共17页
Java 8 新特性概述.docx_第8页
第8页 / 共17页
Java 8 新特性概述.docx_第9页
第9页 / 共17页
Java 8 新特性概述.docx_第10页
第10页 / 共17页
Java 8 新特性概述.docx_第11页
第11页 / 共17页
Java 8 新特性概述.docx_第12页
第12页 / 共17页
Java 8 新特性概述.docx_第13页
第13页 / 共17页
Java 8 新特性概述.docx_第14页
第14页 / 共17页
Java 8 新特性概述.docx_第15页
第15页 / 共17页
Java 8 新特性概述.docx_第16页
第16页 / 共17页
Java 8 新特性概述.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Java 8 新特性概述.docx

《Java 8 新特性概述.docx》由会员分享,可在线阅读,更多相关《Java 8 新特性概述.docx(17页珍藏版)》请在冰点文库上搜索。

Java 8 新特性概述.docx

Java8新特性概述

Java8新特性概述

函数式接口

Java8引入的一个核心概念是函数式接口(FunctionalInterfaces)。

通过在接口里面添加一个抽象方法,这些方法可以直接从接口中运行。

如果一个接口定义个唯一一个抽象方法,那么这个接口就成为函数式接口。

同时,引入了一个新的注解:

@FunctionalInterface。

可以把他它放在一个接口前,表示这个接口是一个函数式接口。

这个注解是非必须的,只要接口只包含一个方法的接口,虚拟机会自动判断,不过最好在接口上使用注解@FunctionalInterface进行声明。

在接口中添加了@FunctionalInterface的接口,只允许有一个抽象方法,否则编译器也会报错。

java.lang.Runnable就是一个函数式接口。

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

@FunctionalInterface

publicinterfaceRunnable{

publicabstractvoidrun();

}

Lambda表达式

函数式接口的重要属性是:

我们能够使用Lambda实例化它们,Lambda表达式让你能够将函数作为方法参数,或者将代码作为数据对待。

Lambda表达式的引入给开发者带来了不少优点:

在Java8之前,匿名内部类,监听器和事件处理器的使用都显得很冗长,代码可读性很差,Lambda表达式的应用则使代码变得更加紧凑,可读性增强;Lambda表达式使并行操作大集合变得很方便,可以充分发挥多核CPU的优势,更易于为多核处理器编写代码;

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

第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:

->;第三部分为方法体,可以是表达式和代码块。

语法如下:

1.方法体为表达式,该表达式的值作为返回值返回。

(parameters)->expression

2.方法体为代码块,必须用{}来包裹起来,且需要一个return返回值,但若函数式接口里面方法返回值是void,则无需返回值。

(parameters)->{statements;}//例如,下面是使用匿名内部类和Lambda表达式的代码比较。

下面是用匿名内部类的代码:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

button.addActionListener(newActionListener(){

pre">@Override

pre">publicvoidactionPerformed(ActionEvente){

pre">System.out.print("HellloLambdainactionPerformed");

pre">}

});

下面是使用Lambda表达式后:

button.addActionListener(

pre">//actionPerformed有一个参数e传入,所以用(ActionEvente)

pre">(ActionEvente)->

pre">System.out.print("HellloLambdainactionPerformed")

);

上面是方法体包含了参数传入(ActionEvente),如果没有参数则只需(),例如Thread中的run方法就没有参数传入,当它使用Lambda表达式后:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

Threadt=newThread(

pre">//run没有参数传入,所以用(),后面用{}包起方法体

pre">()->{

pre">System.out.println("Hellofromathreadinrun");

pre">}

);

/*通过上面两个代码的比较可以发现使用Lambda表达式可以简化代码,并提高代码的可读性。

为了进一步简化Lambda表达式,可以使用方法引用。

例如,下面三种分别是使用内部类,使用Lambda表示式和使用方法引用方式的比较:

*/

//1.使用内部类

Functionf=newFunction(){

pre">@Override

pre">publicStringapply(Integert){

pre">returnnull;

pre">}

};

//2.使用Lambda表达式

Functionf2=(t)->String.valueOf(t);

//3.使用方法引用的方式

Functionf1=String:

:

valueOf;

要使用Lambda表达式,需要定义一个函数式接口,这样往往会让程序充斥着过量的仅为Lambda表达式服务的函数式接口。

为了减少这样过量的函数式接口,Java8在java.util.function中增加了不少新的函数式通用接口。

例如:

Function

将T作为输入,返回R作为输出,他还包含了和其他函数组合的默认方法。

Predicate

将T作为输入,返回一个布尔值作为输出,该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(与、或、非)。

Consumer

将T作为输入,不返回任何内容,表示在单个参数上的操作。

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

//例如,People类中有一个方法getMaleList需要获取男性的列表,这里需要定义一个函数式接口PersonInterface:

interfacePersonInterface{

pre">publicbooleantest(Personperson);

}

publicclassPeople{

pre">privateListpersons=newArrayList();

pre">publicListgetMaleList(PersonInterfacefilter){

pre">Listres=newArrayList();

pre">persons.forEach(

pre">(Personperson)->

pre">{

pre">if(filter.test(person)){//调用PersonInterface的方法

pre">res.add(person);

pre">}

pre">}

);

returnres;

}

}

//为了去除PersonInterface这个函数式接口,可以用通用函数式接口Predicate替代如下:

classPeople{

pre">privateListpersons=newArrayList();

pre">publicListgetMaleList(Predicatepredicate){

pre">Listres=newArrayList();

pre">persons.forEach(

pre">person->{

pre">if(predicate.test(person)){//调用Predicate的抽象方法test

pre">res.add(person);

pre">}

});

returnres;

}

}

接口的增强

Java8对接口做了进一步的增强。

在接口中可以添加使用default关键字修饰的非抽象方法。

还可以在接口中定义静态方法。

如今,接口看上去与抽象类的功能越来越类似了。

默认方法

Java8还允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法。

在实现该接口时,该默认扩展方法在子类上可以直接使用,它的使用方式类似于抽象类中非抽象成员方法。

但扩展方法不能够重载Object中的方法。

例如:

toString、equals、hashCode不能在接口中被重载。

例如,下面接口中定义了一个默认方法count(),该方法可以在子类中直接使用。

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

publicinterfaceDefaultFunInterface{

pre">//定义默认方法count

pre">defaultintcount(){

pre">return1;

pre">}

}

publicclassSubDefaultFunClassimplementsDefaultFunInterface{

pre">publicstaticvoidmain(String[]args){

pre">//实例化一个子类对象,改子类对象可以直接调用父接口中的默认方法count

pre">SubDefaultFunClasssub=newSubDefaultFunClass();

pre">sub.count();

pre">}

}

静态方法

在接口中,还允许定义静态的方法。

接口中的静态方法可以直接用接口来调用。

例如,下面接口中定义了一个静态方法find,该方法可以直接用StaticFunInterface.find()来调用。

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

publicinterfaceStaticFunInterface{

pre">publicstaticintfind(){

pre">return1;

pre">}

}

publicclassTestStaticFun{

pre">publicstaticvoidmain(String[]args){

pre">//接口中定义了静态方法find直接被调用

pre">StaticFunInterface.fine();

pre">}

}

集合之流式操作

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

根据操作返回的结果不同,流式操作分为中间操作和最终操作两种。

最终操作返回一特定类型的结果,而中间操作返回流本身,这样就可以将多个操作依次串联起来。

根据流的并发性,流又可以分为串行和并行两种。

流式操作实现了集合的过滤、排序、映射等功能。

Stream和Collection集合的区别:

Collection是一种静态的内存数据结构,而Stream是有关计算的。

前者是主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU实现计算。

串行和并行的流

流有串行和并行两种,串行流上的操作是在一个线程中依次完成,而并行流则是在多个线程上同时执行。

并行与串行的流可以相互切换:

通过stream.sequential()返回串行的流,通过stream.parallel()返回并行的流。

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

下面是分别用串行和并行的方式对集合进行排序。

串行排序:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

Listlist=newArrayList();

for(inti=0;i<1000000;i++){

pre">doubled=Math.random()*1000;

pre">list.add(d+"");

}

longstart=System.nanoTime();//获取系统开始排序的时间点

intcount=(int)((Stream)list.stream().sequential()).sorted().count();

longend=System.nanoTime();//获取系统结束排序的时间点

longms=TimeUnit.NANOSECONDS.toMillis(end-start);//得到串行排序所用的时间

System.out.println(ms+”ms”);

并行排序:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

Listlist=newArrayList();

for(inti=0;i<1000000;i++){

pre">doubled=Math.random()*1000;

pre">list.add(d+"");

}

longstart=System.nanoTime();//获取系统开始排序的时间点

intcount=(int)((Stream)list.stream().parallel()).sorted().count();

longend=System.nanoTime();//获取系统结束排序的时间点

longms=TimeUnit.NANOSECONDS.toMillis(end-start);//得到并行排序所用的时间

System.out.println(ms+”ms”);

串行输出为1200ms,并行输出为800ms。

可见,并行排序的时间相比较串行排序时间要少不少。

中间操作

该操作会保持stream处于中间状态,允许做进一步的操作。

它返回的还是的Stream,允许更多的链式操作。

常见的中间操作有:

filter():

对元素进行过滤;

sorted():

对元素排序;

map():

元素的映射;

distinct():

去除重复元素;

subStream():

获取子Stream等。

例如,下面是对一个字符串集合进行过滤,返回以“s”开头的字符串集合,并将该集合依次打印出来:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

list.stream().filter((s)->s.startsWith("s")).forEach(System.out:

:

println);

这里的filter(...)就是一个中间操作,该中间操作可以链式地应用其他Stream操作。

终止操作

该操作必须是流的最后一个操作,一旦被调用,Stream就到了一个终止状态,而且不能再使用了。

常见的终止操作有:

forEach():

对每个元素做处理;

toArray():

把元素导出到数组;

findFirst():

返回第一个匹配的元素;

anyMatch():

是否有匹配的元素等。

例如,下面是对一个字符串集合进行过滤,返回以“s”开头的字符串集合,并将该集合依次打印出来:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

list.stream()//获取列表的stream操作对象

.filter((s)->s.startsWith("s"))//对这个流做过滤操作

.forEach(System.out:

:

println);

这里的forEach(...)就是一个终止操作,该操作之后不能再链式的添加其他操作了。

注解的更新

对于注解,Java8主要有两点改进:

类型注解和重复注解。

Java8的类型注解扩展了注解使用的范围。

在该版本之前,注解只能是在声明的地方使用。

现在几乎可以为任何东西添加注解:

局部变量、类与接口,就连方法的异常也能添加注解。

新增的两个注释的程序元素类型ElementType.TYPE_USE和ElementType.TYPE_PARAMETER用来描述注解的新场合。

ElementType.TYPE_PARAMETER表示该注解能写在类型变量的声明语句中。

而ElementType.TYPE_USE表示该注解能写在使用类型的任何语句中(例如声明语句、泛型和强制转换语句中的类型)。

对类型注解的支持,增强了通过静态分析工具发现错误的能力。

原先只能在运行时发现的问题可以提前在编译的时候被排查出来。

Java8本身虽然没有自带类型检测的框架,但可以通过使用CheckerFramework这样的第三方工具,自动检查和确认软件的缺陷,提高生产效率。

例如,下面的代码可以通过编译,但是运行时会报NullPointerException的异常。

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

publicclassTestAnno{

pre">publicstaticvoidmain(String[]args){

pre">Objectobj=null;

pre">obj.toString();

pre">}

}

为了能在编译期间就自动检查出这类异常,可以通过类型注解结合CheckerFramework提前排查出来:

[java]viewplaincopyprint?

在CODE上查看代码片派生到我的代码片

importorg.checkerframework.checker.nullness.qual.NonNull;

publicclassTestAnno{

pre">publicstaticvoidmain(String[]args){

pre">@NonNullObjectobj=null;

pre">obj.toString();

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2