深圳做网站价比高的公司性,wordpress能做cms系统,自动成交型网站建设,有效的网站推广方案编者注#xff1a;在本文中#xff0c;我们提供了全面的Java 8功能教程。 自Java 8公开发布以来已经有一段时间了#xff0c;所有迹象都表明这是一个非常重要的版本。 我们在Java Code Geeks处提供了大量教程#xff0c;例如“ 玩Java 8 – Lambda和并发” #xff0c;“… 编者注在本文中我们提供了全面的Java 8功能教程。 自Java 8公开发布以来已经有一段时间了所有迹象都表明这是一个非常重要的版本。 我们在Java Code Geeks处提供了大量教程例如“ 玩Java 8 – Lambda和并发” “ Java 8 Date Time API教程 JDK 8时代的 LocalDateTime和抽象类与接口” 。 我们还引用了其他来源的15篇必读Java 8教程 。 当然我们还研究了一些不足之处例如Java 8的黑暗面 。 现在是时候将所有Java 8的主要功能集中到一本参考文章中以使您阅读愉快。 请享用 目录 1.简介 2. Java语言的新功能 2.1。 Lambda和功能接口 2.2。 接口默认方法和静态方法 2.3。 方法参考 2.4。 重复注释 2.5。 更好的类型推断 2.6。 扩展注释支持 3. Java编译器的新功能 3.1。 参数名称 4. Java库中的新功能 4.1。 可选的 4.2。 流 4.3。 日期/时间APIJSR 310 4.4。 Nashorn JavaScript引擎 4.5。 Base64 4.6。 平行阵列 4.7。 并发 5.新的Java工具 5.1。 Nashorn引擎jjs 5.2。 类依赖分析器jdeps 6. Java运行时JVM的新功能 7.结论 8.资源 1.简介 毫无疑问 Java 8发行版是Java 5以来Java发行版早在2004年发布以来最伟大的事情。 它为Java带来了许多新功能包括一种语言其编译器库工具以及JVMJava虚拟机本身。 在本教程中我们将研究所有这些更改并在实际示例中演示不同的使用场景。 本教程由几个部分组成每个部分都涉及平台的特定方面 语言 编译器 图书馆 工具 运行时JVM 2. Java语言的新功能 Java 8无论如何都是主要版本。 可能有人说要实现每个Java开发人员正在寻找的功能最终确定都花了很长时间。 在本节中我们将介绍其中的大部分内容。 Lambda和功能接口 Lambda也称为闭包是整个Java 8版本中最大最期待的语言更改。 它们使我们可以将功能视为方法参数传递函数或将代码视为数据每个功能开发人员都非常熟悉的概念。 从第一天开始JVM平台上的许多语言Groovy Scala等等都具有lambda但是Java开发人员别无选择只能用样板匿名类来破坏lambda。 Lambdas设计讨论花费了大量时间和社区精力。 但是最后我们找到了折衷方案从而导致了新的简洁紧凑的语言结构。 以最简单的形式lambda可以表示为以逗号分隔的参数列表即–符号和主体。 例如 Arrays.asList( a , b , d ).forEach( e - System.out.println( e ) ); 请注意参数e的类型是由编译器推断的。 或者您可以显式提供参数的类型并将定义包装在方括号中。 例如 Arrays.asList( a , b , d ).forEach( ( String e ) - System.out.println( e ) ); 如果lambda的主体更复杂则可以将其包装在方括号中就像Java中常用的函数定义一样。 例如 Arrays.asList( a , b , d ).forEach( e - { System.out.print( e ); System.out.print( e ); } ); Lambda可以引用类成员和局部变量如果没有则暗指使它们有效地成为最终变量。 例如这两个片段是等效的 String separator , ; Arrays.asList( a , b , d ).forEach( ( String e ) - System.out.print( e separator ) ); 和 final String separator , ; Arrays.asList( a , b , d ).forEach( ( String e ) - System.out.print( e separator ) ); Lambda可能会返回一个值。 返回值的类型将由编译器推断。 如果lambda主体是单线的则不需要return语句。 以下两个代码段是等效的 Arrays.asList( a , b , d ).sort( ( e1, e2 ) - e1.compareTo( e2 ) ); 和 Arrays.asList( a , b , d ).sort( ( e1, e2 ) - { int result e1.compareTo( e2 ); return result; } ); 语言设计师对如何使已经存在的功能实现lambda友好性进行了大量思考。 结果出现了功能接口的概念。 函数接口是只有一种方法的接口。 这样它可以隐式转换为lambda表达式。 java.lang.Runnable和java.util.concurrent.Callable是功能接口的两个很好的例子。 实际上功能接口是易碎的如果有人在接口定义中仅添加了另一种方法它将不再起作用并且编译过程将失败。 为了克服这种脆弱性并明确声明接口的作用Java 8添加了特殊的注解FunctionalInterfaceJava库中所有现有的接口也已使用FunctionalInterface进行注解。 让我们看一下这个简单的功能接口定义 FunctionalInterface public interface Functional { void method(); } 要记住的一件事 默认方法和静态方法不会破坏功能接口协定可以声明为 FunctionalInterface public interface FunctionalDefaultMethods { void method(); default void defaultMethod() { } } Lambda是Java 8的最大卖点。它有潜力吸引越来越多的开发人员使用这个强大的平台并为纯Java中的函数式编程概念提供最新的支持。 有关更多详细信息请参阅官方文档 。 接口的默认方法和静态方法 Java 8用两个新概念扩展了接口声明默认方法和静态方法。 默认方法使接口在某种程度上类似于特征但目标有所不同。 它们允许向现有接口添加新方法而不会破坏与为这些接口的较早版本编写的代码的二进制兼容性。 默认方法和抽象方法之间的区别在于需要实现抽象方法。 但是默认方法不是。 相反每个接口都必须提供所谓的默认实现并且所有实现者都将默认继承它可以在需要时覆盖此默认实现。 让我们看下面的例子。 private interface Defaulable { // Interfaces now allow default methods, the implementer may or // may not implement (override) them. default String notRequired() { return Default implementation ; } } private static class DefaultableImpl implements Defaulable { } private static class OverridableImpl implements Defaulable { Override public String notRequired() { return Overridden implementation ; } } 接口Defaulable使用关键字default作为方法定义的一部分来声明默认方法notRequired 。 其中一个类DefaultableImpl实现了此接口而保留了默认方法的实现。 另一个OverridableImpl重写默认实现并提供自己的实现。 Java 8提供的另一个有趣的功能是接口可以声明并提供实现静态方法。 这是一个例子。 private interface DefaulableFactory { // Interfaces now allow static methods static Defaulable create( Supplier Defaulable supplier ) { return supplier.get(); } } 下面的小代码段将上面示例中的默认方法和静态方法粘合在一起。 public static void main( String[] args ) { Defaulable defaulable DefaulableFactory.create( DefaultableImpl:: new ); System.out.println( defaulable.notRequired() ); defaulable DefaulableFactory.create( OverridableImpl:: new ); System.out.println( defaulable.notRequired() ); } 该程序的控制台输出如下所示 Default implementation Overridden implementation JVM上的默认方法实现非常有效并且方法调用的字节码指令支持该方法。 默认方法允许现有的Java接口发展而不会中断编译过程。 很好的例子是添加到java.util.Collection接口的大量方法 stream parallelStream forEach removeIf …… 尽管功能强大但应谨慎使用默认方法在将方法声明为默认方法之前最好三思如果确实需要则可能会导致复杂层次结构中的歧义和编译错误。 有关更多详细信息请参阅官方文档 。 方法参考 方法引用提供了有用的语法可以直接引用现有的方法或Java类或对象实例的构造函数。 与Lambdas表达式结合使用时方法引用使语言构造看起来紧凑而简洁从而简化了样板。 下面将Car类作为不同方法定义的示例让我们区分四种受支持的方法引用类型。 public static Car { class Car { public static Car create( final Supplier Car supplier ) { return supplier.get(); } public static void collide( final Car car ) { System.out.println( Collided car.toString() ); } public void follow( final Car another ) { System.out.println( Following the another.toString() ); } public void repair() { System.out.println( Repaired this .toString() ); } } 方法引用的第一类是语法为Class :: new的构造方法引用或者对于泛型为Class T :: new 。 请注意构造函数没有参数。 final Car car Car.create( Car:: new ); final List Car cars Arrays.asList( car ); 第二种类型是使用语法Class :: static_method引用静态方法。 请注意该方法仅接受Car类型的一个参数。 cars.forEach( Car::collide ); 第三种类型是使用语法Class :: method引用特定类型的任意对象的实例方法 。 请注意该方法不接受任何参数。 cars.forEach( Car::repair ); 最后第四种类型是对特定类实例的实例方法的引用即语法instance :: method 。 请注意该方法只接受Car类型的一个参数。 final Car police Car.create( Car:: new ); cars.forEach( police::follow ); 将所有这些示例作为Java程序运行会在控制台上产生以下输出实际的Car实例可能有所不同 Collided com.javacodegeeks.java8.method.references.MethodReferences$Car 7a81197d Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car 7a81197d Following the com.javacodegeeks.java8.method.references.MethodReferences$Car 7a81197d 有关方法引用的更多示例和详细信息请参考官方文档。 重复注释 自从Java 5引入了注释支持以来此功能就非常流行并且得到了广泛的使用。 但是注释使用的局限性之一是不能在同一位置多次声明同一注释。 Java 8违反了此规则并引入了重复注释。 它允许相同的注释在声明的位置重复多次。 重复的注释本身应使用Repeatable注释进行注释。 实际上这不是语言更改而是更多的编译器技巧因为该技术的原理保持不变。 让我们看一个简单的例子 package com.javacodegeeks.java8.repeatable.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class RepeatingAnnotations { Target ( ElementType.TYPE ) Retention ( RetentionPolicy.RUNTIME ) public interface Filters { Filter[] value(); } Target ( ElementType.TYPE ) Retention ( RetentionPolicy.RUNTIME ) Repeatable ( Filters. class ) public interface Filter { String value(); }; Filter ( filter1 ) Filter ( filter2 ) public interface Filterable { } public static void main(String[] args) { for ( Filter filter: Filterable. class .getAnnotationsByType( Filter. class ) ) { System.out.println( filter.value() ); } } } 正如我们所看到的是一个注释类过滤器与Repeatable过滤器。 类 注解。 过滤器只是过滤器注释的持有者但是Java编译器试图向开发人员隐藏其存在。 因此 Filterable接口具有两次定义的Filter注释没有提及Filters 。 此外反射API提供了新的方法getAnnotationsByType返回某种类型的重复注释请注意筛选。 类 .getAnnotation过滤器。 类 将返回过滤器的编译器注入的情况下。 程序输出如下所示 filter1 filter2 有关更多详细信息请参阅官方文档 。 更好的类型推断 Java 8编译器在类型推断方面进行了很多改进。 在许多情况下可以通过使代码保持整洁的编译器来推断显式类型参数。 让我们看一个例子。 package com.javacodegeeks.java8.type.inference; public class Value T { public static T T defaultValue() { return null ; } public T getOrDefault( T value, T defaultValue ) { return ( value ! null ) ? value : defaultValue; ) ? value : defaultValue; } } 这是Value String类型的用法。 package com.javacodegeeks.java8.type.inference; public class TypeInference { public static void main(String[] args) { final Value String value new Value(); value.getOrDefault( 22 , Value.defaultValue() ); } } Value的类型参数。 推断出defaultValue 不需要提供该值。 在Java 7中相同的示例将无法编译应将其重写为Value。String defaultValue 。 扩展注释支持 Java 8扩展了可以使用注释的上下文。 现在几乎可以注释所有内容局部变量泛型类型超类和实现接口甚至是方法的异常声明。 下面是几个示例。 package com.javacodegeeks.java8.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Collection; public class Annotations { Retention ( RetentionPolicy.RUNTIME ) Target ( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } ) public interface NonEmpty { } public static class Holder NonEmpty T extends NonEmpty Object { public void method() throws NonEmpty Exception { } } SuppressWarnings ( unused ) public static void main(String[] args) { final Holder String holder new NonEmpty Holder String (); NonEmpty Collection NonEmpty String strings new ArrayList(); } } ElementType。 TYPE_USE和ElementType。 TYPE_PARAMETER是两种新的元素类型用于描述适用的注释上下文。 Annotation Processing API也进行了一些小的更改以识别Java编程语言中的那些新类型的注释。 3. Java编译器的新功能 参数名称 从字面上看Java开发人员已经发明了各种方法来将方法参数名称保留为Java字节码 并使它们在运行时可用例如Paranamer库 。 最后Java 8将此要求苛刻的功能烘焙到语言中使用Reflection API和Parameter.getName方法和字节码使用新的javac编译器参数–parameters 。 package com.javacodegeeks.java8.parameter.names; import java.lang.reflect.Method; import java.lang.reflect.Parameter; public class ParameterNames { public static void main(String[] args) throws Exception { Method method ParameterNames. class .getMethod( main , String[]. class ); for ( final Parameter parameter: method.getParameters() ) { System.out.println( Parameter: parameter.getName() ); } } } 如果在不使用–parameters参数的情况下编译此类然后运行该程序则会看到类似以下内容 Parameter: arg0 将–parameters参数传递给编译器后程序输出将有所不同将显示参数的实际名称 Parameter: args 对于有经验的Maven用户 可以使用maven-compiler-plugin的 configuration部分将–parameters参数添加到编译器中 plugin groupId org.apache.maven.plugins/ groupId artifactId maven-compiler-plugin/ artifactId version 3.1/ version configuration compilerArgument -parameters/ compilerArgument source 1.8/ source target 1.8/ target / configuration / plugin 带有Java 8的最新Eclipse Kepler SR2版本请查看此下载说明 支持提供了有用的配置选项来控制此编译器设置如下图所示。 图1.配置Eclipse项目以支持新的Java 8编译器–parameters参数 另外为了验证参数名称的可用性 Parameter类提供了一种方便的方法isNamePresent 。 4. Java库中的新功能 Java 8添加了许多新类并扩展了现有类以便为现代并发函数式编程日期/时间等提供更好的支持。 可选的 迄今为止 著名的NullPointerException是Java应用程序失败的最常见原因。 很久以前伟大的Google Guava项目引入了Optional作为NullPointerException的解决方案通过空检查防止代码库污染并鼓励开发人员编写更干净的代码。 受Google Guava的启发 Optional现在是Java 8库的一部分。 可选的只是一个容器它可以保存某个T类型的值 或者可以为null 。 它提供了许多有用的方法因此显式null检查不再有任何借口。 请参阅Java 8官方文档以获取更多详细信息。 我们将看一下Optional用法的两个小例子具有可为空的值和不允许为null的值。 Optional String fullName Optional.ofNullable( null ); System.out.println( Full Name is set? fullName.isPresent() ); System.out.println( Full Name: fullName.orElseGet( () - [none] ) ); System.out.println( fullName.map( s - Hey s ! ).orElse( Hey Stranger! ) ); 如果Optional的此实例具有非null值则isPresent方法返回true否则返回false 。 如果Optional通过接受生成默认值的函数为null 则orElseGet方法提供了后备机制。 map方法转换当前Optional的值并返回新的Optional实例。 orElse方法类似于orElseGet但它接受函数默认值而不是函数。 这是该程序的输出 Full Name is set? false Full Name: [none] Hey Stranger! 让我们简要地看一下另一个例子 Optional String firstName Optional.of( Tom ); System.out.println( First Name is set? firstName.isPresent() ); System.out.println( First Name: firstName.orElseGet( () - [none] ) ); System.out.println( firstName.map( s - Hey s ! ).orElse( Hey Stranger! ) ); System.out.println(); 这是输出 First Name is set? true First Name: Tom Hey Tom! 有关更多详细信息请参阅官方文档。 流 新添加的Stream API java.util.stream 在Java 中引入了现实世界中的函数式编程。 到目前为止这是Java库中最全面的扩展旨在通过允许Java开发人员编写有效简洁简洁的代码来提高他们的生产力。 Stream API大大简化了集合的处理但不仅限于Java集合我们将在后面看到。 让我们从名为Task的简单类开始。 public class Streams { private enum Status { OPEN, CLOSED }; private static final class Task { private final Status status; private final Integer points; Task( final Status status, final Integer points ) { this .status status; this .points points; } public Integer getPoints() { return points; } public Status getStatus() { return status; } Override public String toString() { return String.format( [%s, %d] , status, points ); } } } Task具有一些点或伪复杂性概念可以为OPEN或CLOSED 。 然后让我们介绍一些要处理的任务。 final Collection Task tasks Arrays.asList( new Task( Status.OPEN, 5 ), new Task( Status.OPEN, 13 ), new Task( Status.CLOSED, 8 ) ); 我们要解决的第一个问题是所有OPEN任务总共有多少点 在Java 8之前通常的解决方案是某种foreach迭代。 但是在Java 8中答案是流支持顺序和并行聚合操作的一系列元素。 // Calculate total points of all active tasks using sum() final long totalPointsOfOpenTasks tasks .stream() .filter( task - task.getStatus() Status.OPEN ) .mapToInt( Task::getPoints ) .sum(); System.out.println( Total points: totalPointsOfOpenTasks ); 控制台上的输出如下所示 Total points: 18 这里发生了几件事。 首先将任务集合转换为其流表示形式。 然后对流的过滤操作将所有已关闭的任务过滤掉。 上下一步骤中mapToInt操作任务 S的整数 s使用每个任务实例的任务:: getPoints方法的流的流转换。 最后使用求和方法对所有点求和得出最终结果。 在继续下一个示例之前需要注意一些有关流的注意事项 此处有更多详细信息 。 流操作分为中间操作和终端操作。 中间操作返回一个新的流。 它们总是很懒惰执行诸如filter之类的中间操作实际上并不执行任何过滤而是创建一个新的流该新流在遍历时将包含与给定谓词匹配的初始流的元素。 终端操作例如forEach或sum 可能会遍历流以产生结果或副作用。 执行终端操作后流管道被视为已消耗无法再使用。 在几乎所有情况下终端操作人员都很渴望完成对基础数据源的遍历。 流的另一个价值主张是开箱即用的并行处理支持。 让我们看一下这个示例该示例确实总结了所有任务的要点。 // Calculate total points of all tasks final double totalPoints tasks .stream() .parallel() .map( task - task.getPoints() ) // or map( Task::getPoints ) .reduce( 0 , Integer::sum ); System.out.println( Total points (all tasks): totalPoints ); 除了我们尝试并行处理所有任务并使用reduce方法计算最终结果外它与第一个示例非常相似。 这是控制台输出 Total points (all tasks): 26.0 通常需要根据某些标准对收集元素进行分组。 流可以帮助实现这一点下面的示例也将对此进行说明。 // Group tasks by their status final Map Status, List Task map tasks .stream() .collect( Collectors.groupingBy( Task::getStatus ) ); System.out.println( map ); 此示例的控制台输出如下所示 {CLOSED[[CLOSED, 8 ]], OPEN[[OPEN, 5 ], [OPEN, 13 ]]} 为了完成任务示例让我们基于任务集的点来计算每个任务在整个集合中的总体百分比或权重。 // Calculate the weight of each tasks (as percent of total points) final Collection String result tasks .stream() // Stream String .mapToInt( Task::getPoints ) // IntStream .asLongStream() // LongStream .mapToDouble( points - points / totalPoints ) // DoubleStream .boxed() // Stream Double .mapToLong( weigth - ( long )( weigth * // LongStream )( weigth * 100 ) ) // LongStream .mapToObj( percentage - percentage % ) // Stream String .collect( Collectors.toList() ); // List String System.out.println( result ); 控制台输出就在这里 [ 19 %, 50 %, 30 %] 最后如前所述Stream API不仅与Java集合有关。 像逐行读取文本文件这样的典型I / O操作非常适合从流处理中受益。 这是一个确认这一点的小例子。 final Path path new File( filename ).toPath(); try ( Stream String lines Files.lines( path, StandardCharsets.UTF_8 ) ) { lines.onClose( () - System.out.println( Done! ) ).forEach( System.out::println ); } 在流上调用的onClose方法返回具有附加关闭处理程序的等效流。 在流上调用close方法时将运行关闭处理程序。 通过接口的默认方法和静态方法生成的 Stream API以及Lambda和方法引用是Java 8对软件开发中现代范例的响应。 有关更多详细信息请参阅官方文档 。 日期/时间APIJSR 310 Java 8通过提供新的Date-Time APIJSR 310进一步进行了日期和时间管理。 对于Java开发人员而言日期和时间操纵是最糟糕的痛苦之一。 紧随其后的java.util.Calendar标准java.util.Date根本没有改善这种情况可以说使情况更加混乱。 这就是Joda-Time的诞生方式Java的绝佳替代日期/时间API。 Java 8的新Date-Time APIJSR 310受Joda-Time的影响很大并充分利用了它的优势。 新的java.time包包含日期时间日期/时间时区瞬间持续时间和时钟操作的所有类 。 在API的设计中非常认真地考虑了不变性不允许进行任何更改从java.util.Calendar中吸取的艰巨教训。 如果需要修改将返回相应类的新实例。 让我们看一下关键类及其用法示例。 第一类是时钟 它使用时区提供对当前时刻日期和时间的访问。 可以使用Clock代替System.currentTimeMillis和TimeZone.getDefault 。 // Get the system clock as UTC offset final Clock clock Clock.systemUTC(); System.out.println( clock.instant() ); System.out.println( clock.millis() ); 控制台上的示例输出 2014 - 04 2014 -12T15: 19 : 29 .282Z 1397315969360 我们将要查看的其他新类是LocaleDate和LocalTime 。 在ISO- 8601日历系统中LocaleDate仅保存日期部分没有时区。 分别地 LocaleTime在ISO- 8601日历系统中仅保存没有时区的时间部分 。 LocaleDate和LocaleTime都可以从Clock创建。 // Get the local date and local time final LocalDate date LocalDate.now(); final LocalDate dateFromClock LocalDate.now( clock ); System.out.println( date ); System.out.println( dateFromClock ); // Get the local date and local time final LocalTime time LocalTime.now(); final LocalTime timeFromClock LocalTime.now( clock ); System.out.println( time ); System.out.println( timeFromClock ); 控制台上的示例输出 2014 - 04 - 12 2014 - 04 - 12 11 : 25 : 54.568 15 : 25 : 54.568 LocalDateTime将LocaleDate和LocalTime结合在一起并在ISO-8601日历系统中保存带时间的日期但没有时区。 快速示例如下所示。 // Get the local date/time final LocalDateTime datetime LocalDateTime.now(); final LocalDateTime datetimeFromClock LocalDateTime.now( clock ); System.out.println( datetime ); System.out.println( datetimeFromClock ); 控制台上的示例输出 2014 - 04 2014 -12T11: 37 : 52.309 2014 - 04 2014 -12T15: 37 : 52.309 如果您需要特定时区的日期/时间则可以使用ZonedDateTime来提供帮助。 在ISO-8601日历系统中它保存带有日期和时区的日期。 这是不同时区的几个示例。 // Get the zoned date/time final ZonedDateTime zonedDatetime ZonedDateTime.now(); final ZonedDateTime zonedDatetimeFromClock ZonedDateTime.now( clock ); final ZonedDateTime zonedDatetimeFromZone ZonedDateTime.now( ZoneId.of( America/Los_Angeles ) ); System.out.println( zonedDatetime ); System.out.println( zonedDatetimeFromClock ); System.out.println( zonedDatetimeFromZone ); 控制台上的示例输出 2014 - 04 -12T11: 47 : 01.017 - 04 : 00 [America/New_York] 2014 - 04 2014 -12T15: 47 : 01 .017Z 2014 - 04 -12T08: 47 : 01.017 - 07 : 00 [America/Los_Angeles] 最后让我们看一下Duration类以秒和纳秒为单位的时间量。 计算两个日期之间的差异非常容易。 让我们来看看。 // Get duration between two dates final LocalDateTime from LocalDateTime.of( 2014 , Month.APRIL, 16 , 0 , 0 , 0 ); final LocalDateTime to LocalDateTime.of( 2015 , Month.APRIL, 16 , 23 , 59 , 59 ); final Duration duration Duration.between( from, to ); System.out.println( Duration in days: duration.toDays() ); System.out.println( Duration in hours: duration.toHours() ); 上面的示例计算了2014 年4月16日至2015年 4月 16日这两个日期之间的持续时间以天和小时为单位。 这是控制台上的示例输出 Duration in days: 365 Duration in hours: 8783 关于Java 8的新日期/时间API的总体印象是非常非常积极的。 部分是由于它经过了久经考验的基础 Joda-Time 部分是因为这一次最终得到了认真解决并听到了开发人员的声音。 有关更多详细信息请参阅官方文档 。 Nashorn JavaScript引擎 Java 8附带了新的Nashorn JavaScript引擎 该引擎允许在JVM上开发和运行某些类型JavaScript应用程序。 Nashorn JavaScript引擎只是javax.script.ScriptEngine的另一种实现并且遵循相同的规则集从而允许Java和JavaScript互操作。 这是一个小例子。 ScriptEngineManager manager new ScriptEngineManager(); ScriptEngine engine manager.getEngineByName( JavaScript ); System.out.println( engine.getClass().getName() ); System.out.println( Result: engine.eval( function f() { return 1; }; f() 1; ) ); 控制台上的示例输出 jdk.nashorn.api.scripting.NashornScriptEngine Result: 2 我们将在后面专门讨论新Java工具的部分中回到Nashorn。 Base64 最后随着Java 8版本的发布 对Base64编码的支持已进入Java标准库。 如以下示例所示它非常易于使用。 package com.javacodegeeks.java8.base64; import java.nio.charset.StandardCharsets; import java.util.Base64; public class Base64s { public static void main(String[] args) { final String text Base64 finally in Java 8! ; final String encoded Base64 .getEncoder() .encodeToString( text.getBytes( StandardCharsets.UTF_8 ) ); System.out.println( encoded ); final String decoded new String( Base64.getDecoder().decode( encoded ), StandardCharsets.UTF_8 ); System.out.println( decoded ); } } 程序运行的控制台输出显示编码和解码的文本 QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ Base64 finally in Java 8 ! Base64类 Base64。getUrlEncoder / Base64。getUrlDecoder Base64。getMimeEncoder / Base64。getMimeDecoder 还提供URL友好的编码器/解码器和MIME友好的编码器/解码器。 平行阵列 Java 8版本增加了许多新方法来允许并行数组处理。 可以说最重要的一个是parallelSort 它可以显着加快多核计算机上的排序速度。 下面的小示例演示了该新方法家族 parallelXxx 的实际作用。 package com.javacodegeeks.java8.parallel.arrays; import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; public class ParallelArrays { public static void main( String[] args ) { long [] arrayOfLong new long [ 20000 ]; Arrays.parallelSetAll( arrayOfLong, index - ThreadLocalRandom.current().nextInt( 1000000 ) ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i - System.out.print( i ) ); System.out.println(); Arrays.parallelSort( arrayOfLong ); Arrays.stream( arrayOfLong ).limit( 10 ).forEach( i - System.out.print( i ) ); System.out.println(); } } 这个小代码段使用方法parallelSetAll填充具有20000个随机值的数组。 之后将应用parallelSort 。 程序在排序前后会输出前10个元素以确保数组真正有序。 示例程序输出看起来像这样请注意数组元素是随机生成的 Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378 Sorted: 39 220 263 268 325 607 655 678 723 793 并发 新方法已添加到java.util.concurrent.ConcurrentHashMap类中以支持基于新添加的流功能和lambda表达式的聚合操作。 另外已经将新方法添加到java.util.concurrent.ForkJoinPool类中以支持公用池另请参见有关Java并发性的免费课程 。 添加了新的java.util.concurrent.locks.StampedLock类以提供具有三种模式的基于功能的锁用于控制读/写访问它可能被认为是臭名昭著的java.util.concurrent.locks.ReadWriteLock的替代方法。 。 新类已添加到java.util.concurrent.atomic包中 双累加器 双重加法器 长累积器 长加法器 5.新的Java工具 Java 8附带了一组新的命令行工具。 在本节中我们将研究其中最有趣的部分。 Nashorn引擎jjs jjs是基于命令行的独立Nashorn引擎。 它接受JavaScript源代码文件列表作为参数并运行它们。 例如让我们创建一个具有以下内容的文件func.js function f() { return 1 ; }; print( f() 1 ); 要从命令执行此fie让我们将其作为参数传递给jjs jjs func.js 控制台上的输出将是 2 有关更多详细信息请参阅官方文档 。 类依赖分析器jdeps jdeps是一个非常出色的命令行工具。 它显示了Java类文件的包级别或类级别的依赖关系。 它接受.class文件 目录或JAR文件作为输入。 默认情况下 jdeps将依赖项输出到系统输出控制台。 例如让我们看一下流行的Spring Framework库的依赖项报告。 为了使示例简短让我们仅分析一个JAR文件 org.springframework.core-3.0.5.RELEASE.jar 。 jdeps org.springframework.core- 3.0 . 5 .RELEASE.jar 该命令输出很多因此我们将对其进行研究。 依赖项按程序包分组。 如果依赖项在类路径上不可用则显示为not found 。 org.springframework.core- 3.0 . 5 .RELEASE.jar - C:\Program Files\Java\jdk1. 8.0 \jre\lib\rt.jar org.springframework.core (org.springframework.core- 3.0 . 5 .RELEASE.jar) - java.io - java.lang - java.lang.annotation - java.lang.ref - java.lang.reflect - java.util - java.util.concurrent - org.apache.commons.logging not found - org.springframework.asm not found - org.springframework.asm.commons not found org.springframework.core.annotation (org.springframework.core- 3.0 . 5 .RELEASE.jar) - java.lang - java.lang.annotation - java.lang.reflect - java.util For more details please refer to official documentation . 6. New Features in Java runtime (JVM) The PermGen space is gone and has been replaced with Metaspace ( JEP 122 ). The JVM options -XX:PermSize and – XX:MaxPermSize have been replaced by -XX:MetaSpaceSize and -XX:MaxMetaspaceSize respectively. 7.结论 The future is here: Java 8 moves this great platform forward by delivering the features to make developers much more productive. It is too early to move the production systems to Java 8 but in the next couples of months its adoption should slowly start growing. Nevertheless the time is right to start preparing your code bases to be compatible with Java 8 and to be ready to turn the switch once Java 8 proves to be safe and stable enough. As a confirmation of community Java 8 acceptance, recently Pivotal released Spring Framework 4.0.3 with production-ready Java 8 support . 如果您喜欢此功能请订阅我们的时事通讯以享受每周更新和免费白皮书 另外请查看我们的课程以获得更高级的培训 You are welcome to contribute with your comments about the exciting new Java 8 features! 8. Resources Some additional resources which discuss in depth different aspects of Java 8 features: Java 8 Tutorials on JCG Examples: https://examples.javacodegeeks.com/?sjava8 Whats New in JDK 8: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html The Java Tutorials: http://docs.oracle.com/javase/tutorial/ WildFly 8, JDK 8, NetBeans 8, Java EE 7: http://blog.arungupta.me/2014/03/wildfly8-jdk8-netbeans8-javaee7-excellent-combo-enterprise-java/ Java 8 Tutorial: http://winterbe.com/posts/2014/03/16/java-8-tutorial/ JDK 8 Command-line Static Dependency Checker: http://marxsoftware.blogspot.ca/2014/03/jdeps.html The Illuminating Javadoc of JDK 8: http://marxsoftware.blogspot.ca/2014/03/illuminating-javadoc-of-jdk-8.html The Dark Side of Java 8: http://blog.jooq.org/2014/04/04/java-8-friday-the-dark-side-of-java-8/ Installing Java™ 8 Support in Eclipse Kepler SR2: http://www.eclipse.org/downloads/java8/ Java 8: http://www.baeldung.com/java8 Oracle Nashorn. A Next-Generation JavaScript Engine for the JVM: http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html Java 8 Features Tutorial was last updated on Oct. 3, 2016 翻译自: https://www.javacodegeeks.com/java-8-features-tutorial.html