石头游戏网

请注意,这个方法接受一个Car类型的参数Car police =

简介: 请注意,这个方法接受一个Car类型的参数Car police = Car.create( Car::);cars.forEach( police::follow );运行上面的Ja程序在控制台上会有下面的输出(Car的

毫无疑问,Ja 8发行版是自Ja 5(发行于2004,已经过了相当一段时间了)以来最具革命性的版本。

这篇教程由以下几部分组成,它们分别涉及到Ja平台某一特定方面的内容:Ja语言编译器类库工具Ja运行时(JVM)2.Ja语言的新特性不管怎么说,Ja 8都是一个变化巨大的版本。

你可能认为Ja 8耗费了大量的时间才得以完成是为了实现了每个Ja程序员所期待的特性。

2.1 Lambda表达式与Functional接口Lambda表达式(也称为闭包)是整个Ja 8发行版中最受期待的在Ja语言层面上的改变,Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据:函数式程序员对这一概念非常熟悉。

在JVM平台上的很多语言(Groovy,Scala,…

可喜的是,最终找到了一个平衡点,使得可以使用一种即简洁又紧凑的新方式来构造Lambdas。

在最简单的形式中,一个lambda可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。

同时,你也可以通过把参数类型与参数包括在括号中的形式直接给出参数的类型:在某些情况下lambda的函数体会更加复杂,这时可以把函数体放到在一对花括号中,就像在Ja中定义普通函数一样。

下面两个代码片段是等价的:和:"a""b""d"int return public Functional {method();}需要记住的一件事是:默认方法与静态方法并不影响函数式接口的契约,可以任意使用:Lambda是Ja 8最大的卖点。

它具有吸引越来越多程序员到Ja平台上的潜力,并且能够在纯Ja语言环境中一种优雅的方式来支持函数式编程。

2.2 接口的默认方法与静态方法Ja 8用默认方法与静态方法这两个新概念来扩展接口的声明。

默认方法使接口有点像Traits(Scala中特征(trait)类似于Ja中的Interface,但它可以包含实现代码,也就是目前Ja8新增的功能),但与传统的接口又有些不一样,它允许在已有的接口中添加新方法,而同时又保持了与旧版本代码的兼容性。

相反,每个接口都必须一个所谓的默认实现,这样所有的接口实现者将会默认继承它(如果有必要的话,可以覆盖这个默认实现)。

在JVM中,默认方法的实现是非常高效的,并且通过字节码指令为方法调用了支持。

默认方法允许继续使用现有的Ja接口,而同时能够保障正常的编译过程。

这方面好的例子是大量的方法被添加到ja.util.Collection接口中去:stream(),parallelStream(),forEach(),removeIf(),…

尽管默认方法非常强大,但是在使用默认方法时我们需要小心注意一个地方:在声明一个默认方法前,请仔细思考是不是真的有必要使用默认方法,因为默认方法会带给程序歧义,并且在复杂的继承中容易产生编译错误。

更多详情请参考官方文档2.3 方法引用方法引用了非常有用的语法,可以直接引用已有Ja类或对象(实例)的方法或构造器。

与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

下面,我们以定义了4个方法的Car这个类作为例子,区分Ja中支持的4种不同的方法引用。

第二种方法引用是静态方法引用,它的语法是Class::static_method。

第三种方法引用是特定类的任意对象的方法引用,它的语法是Class::method。

最后,第四种方法引用是特定对象的方法引用,它的语法是instance::method。

请注意,这个方法接受一个Car类型的参数Car police = Car.create( Car::);cars.forEach( police::follow );运行上面的Ja程序在控制台上会有下面的输出(Car的实例可能不一样):正如我们看到的,这里有个使用@Repeatable( Filters.class )注解的注解类Filter,Filters仅仅是Filter注解的数组,但Ja编译器并不想让程序员意识到Filters的存在。

同时,反射相关的API了新的函数getAnnotationsByType()来返回重复注解的类型(请注意Filterable.class.getAnnotation( Filters.class )经编译器处理后将会返回Filters的实例)。

程序输出结果如下:null}T getOrDefault( T value, T defaultValue ) {( value != ) ? value : defaultValue;public TypeInference {staticmain(String[] args) {Value< String > value = Value<>();"22"}}Value.defaultValue()的参数类型可以被推测出,所以就不必明确给出。

在Ja 7中,相同的例子将不会通过编译,正确的书写方式是 Value.< String >defaultValue()。

现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。

下面演示几个例子:com.jacodegeeks.ja8.annotations;ja.lang.annotation.ElementType;import ja.lang.annotation.RetentionPolicy;import ja.util.ArrayList;import public Annotations {( RetentionPolicy.RUNTIME )( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )@interface}staticHolder< T > @NonEmptypublic method() @NonEmpty }@SuppressWarnings"unused" public void final new Holder< String >(); Collection< String > strings = ArrayList<>(); public ParameterNames {staticmain(String[] args) Exception {class"main"classforfinal System.out.println( + parameter.getName() );}}如果不使用–parameters参数来编译这个类,然后运行这个类,会得到下面的输出:如果使用–parameters参数来编译这个类,程序的结构会有所不同(参数的真实名字将会显示出来):对于有经验的Men用户,通过men-compiler-plugin的配置可以将-parameters参数添加到编译器中去。

plugin<>org.apache.men.pluginsartifactIdartifactId<>3.1configuration<>-parameterssourcesource<>1.8configurationplugin);System.out.println( + fullName.isPresent() ); System.out.println( + fullName.orElseGet( () -> ) );System.out.println( fullName.map( s -> + s + ).orElse( ) );如果Optional类的实例为非空值的话,isPresent()返回true,否从返回false。

map()函数对当前Optional的值进行转化,然后返回一个新的Optional实例。

下面是这个程序的输出:更多详情请参考官方文档4.2 Stream最新添加的Stream API(ja.util.stream) 把真正的函数式编程风格引入到Ja中。

这是目前为止对Ja类库最好的补充,因为Stream API可以极大Ja程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream API极大简化了集合框架的处理(但它的处理的范围不仅仅限于集合框架的处理,这点后面我们会看到)。

在Ja 8以前,一般的解决方式用foreach循环,但是在Ja 8里面我们可以使用stream:一串支持连续、并行聚集操作的元素。

long .stream().mapToInt( Task::getPoints )"Total points: " totalPoints = tasks.parallel()// or map( Task::getPoints )0"Total points (all tasks): " 这个例子的控制台输出如下:让我们来计算整个集合中每个task分数(或权重)的平均值来结束task的例子。

Collection< String > result = tasks// Stream< String >// IntStream// LongStream// DoubleStream// Stream< Double >long100// LongStream"%"// Stream< String>// List< String >System.out.println( result );下面是这个例子的控制台输出:最后,就像前面提到的,Stream API不仅仅处理Ja集合框架。

Path path = File( filename ).toPath();trylines.onClose( () -> System.out.println() ).forEach( System.out::println );}对一个stream对象调用onClose方法会返回一个在原有功能基础上新增了关闭功能的stream对象,当对stream对象调用close()方法时,与关闭相关的处理器就会执行。

Stream API、Lambda表达式与方法引用在接口默认方法与静态方法的配合下是Ja 8对现代软件开发范式的回应。

4.3 Date/Time API (JSR 310)Ja 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

标准的 ja.util.Date以及后来的ja.util.Calendar一点没有改善这种情况(可以这么说,它们一定程度上更加复杂)。

这种情况直接导致了Joda-Time——一个可替换标准日期/时间处理且功能非常强大的Ja API的诞生。

Ja 8新的Date-Time API (JSR 310)在很大程度上受到Joda-Time的影响,并且吸取了其精髓。

新的ja.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

在设计新版API时,十分注重与旧版API的兼容性:不允许有任何的改变(从ja.util.Calendar中得到的深刻教训)。

第一个是Clock类,它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。

Clock clock = Clock.systemUTC();System.out.println( clock.instant() );System.out.println( clock.millis() );下面是程序在控制台上的输出:LocalTime time = LocalTime.now();final2014-04-1211:25:54.56815:25:54.568LocaleDateTime把LocaleDate与LocaleTime的功能合并起来,它持有的是ISO-8601格式无时区信息的日期与时间。

LocalDateTime datetime = LocalDateTime.now();final2014-04-12T15:37:52.309如果你需要特定时区的日期/时间,那么ZonedDateTime是你的选择。

下面是一些不同时区的例子:Get the zoned /timefinal ZonedDateTime zonedDatetime = ZonedDateTime.now();final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( ) );System.out.println( zonedDatetime );System.out.println( zonedDatetimeFromClock );System.out.println( zonedDatetimeFromZone );下面是程序在控制台上的输出:最后,让我们看一下Duration类:在秒与纳秒级别上的一段时间。

下面是程序在控制台上的输出:inin 我们在后面的Ja新工具章节会再次谈到Nashorn。

4.5 Base64在Ja 8中,Base64编码已经成为Ja类库的标准。

它的使用十分简单,下面让我们看一个例子:com.jacodegeeks.ja8.base64;ja.nio.charset.StandardCharsets;import public Base64s {staticmain(String[] args) {String text = ;String encoded = Base64.encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );final new Base64.getDecoder().decode( encoded ),System.out.println( decoded );Base64 finally Ja 8!Base64类同时还了对URL、MIME友好的编码器与(Base64.getUrlEncoder() / Base64.getUrlDecoder(), Base64.getMimeEncoder() / Base64.getMimeDecoder())。

4.6 并行(parallel)数组Ja 8增加了大量的新方法来对数组进行并行处理。

可以说,最重要的是parallelSort()方法,因为它可以在多核机器上极大提高数组排序的速度。

上面的代码片段使用了parallelSetAll()方法来对一个有20000个元素的数组进行随机赋值。

这个程序在控制台上的输出如下(请注意数组元素是随机生产的):11;};-> org.apache.commons.logging not found-> org.springframework.asm.commons not found-> ja.lang -> ja.lang.reflect -> ja.util更多详情请参考官方文档6. Ja虚拟机(JVM)的新特性PermGen空间被移除了,取而代之的是Metaspace(JEP 122)。


以上是文章"

请注意,这个方法接受一个Car类型的参数Car police =

"的内容,欢迎阅读石头游戏网的其它文章