资源预览内容
第1页 / 共21页
第2页 / 共21页
第3页 / 共21页
第4页 / 共21页
第5页 / 共21页
第6页 / 共21页
第7页 / 共21页
第8页 / 共21页
第9页 / 共21页
第10页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
Java 8新特性指南Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。本次培训简述18个新特性。Lambdas表达式Lambda表达式(也称为闭包)是整个Java 8发行版中最受期待的在Java语言层面上的改变,Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据:函数式程序员对这一概念非常熟悉。在JVM平台上的很多语言(Groovy,Scala,)从一开始就有Lambda,但是Java程序员不得不使用毫无新意的匿名类来代替lambda。实例:Arrays.asList( a, b, d ).forEach( e - System.out.println( e ) );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; );Functional接口函数式接口就是一个具有一个方法的普通接口。像这样的接口,可以被隐式转换为lambda表达式。java.lang.Runnable与java.util.concurrent.Callable是函数式接口最典型的两个例子。在实际使用过程中,函数式接口是容易出错的:如有某个人在接口定义中增加了另一个方法,这时,这个接口就不再是函数式的了,并且编译过程也会失败。为了克服函数式接口的这种脆弱性并且能够明确声明接口作为函数式接口的意图,Java 8增加了一种特殊的注解FunctionalInterface(Java 8中所有类库的已有接口都添加了FunctionalInterface注解)。实例:1:FunctionalInterfacepublic interface FunctionalDefaultMethods void method();default void defaultMethod() 2:/Java8之前:newThread(newRunnable()Overridepublicvoidrun()System.out.println(BeforeJava8);).start();/Java8方式:newThread()-System.out.println(InJava8,Lambda).start();接口的默认方法与静态方法Java 8用默认方法与静态方法这两个新概念来扩展接口的声明。默认方法使接口有点像Traits(Scala中特征(trait)类似于Java中的Interface,但它可以包含实现代码,也就是目前Java8新增的功能),但与传统的接口又有些不一样,它允许在已有的接口中添加新方法,而同时又保持了与旧版本代码的兼容性。默认方法与抽象方法不同之处在于抽象方法必须要求实现,但是默认方法则没有这个要求。相反,每个接口都必须提供一个所谓的默认实现,这样所有的接口实现者将会默认继承它(如果有必要的话,可以覆盖这个默认实现)。private interface Defaulable 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; 接口静态方法构造方法调用public class Car public static Car create( final Supplier supplier ) return supplier.get(); public static void collide( final 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() ); public static void main(String args) final Car = Car.create( Car:new );/构造函数调用 final List cars = Arrays.asList( car ); cars.forEach( Car:collide );/静态函数调用 cars.forEach( Car:repair );/特定类的函数函数调用 final Car police = Car.create( Car:new ); cars.forEach( police:follow );/特定函数调用重复注解自从Java 5引入了注解机制,这一特性就变得非常流行并且广为使用。然而,使用注解的一个限制是相同的注解在同一位置只能声明一次,不能声明多次。Java 8打破了这条规则,引入了重复注解机制,这样相同的注解可以在同一地方声明多次。重复注解机制本身必须用Repeatable注解。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 : Filterable.class.getAnnotationsByType( Filter.class ) ) System.out.println( filter.value() ); 类型推测机制public class Value public static T defaultValue() return null; public T getOrDefault( T value, T defaultValue ) return ( value != null ) ? value : defaultValue; public static void main(String args) final Value value = new Value(); value.getOrDefault( 22, Value.defaultValue() ); Java 7中,相同的例子将不会通过编译,正确的书写方式是 Value.defaultValue()扩展注解的支持Java 8扩展了注解的上下文。现在几乎可以为任何东西添加注解:局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。public class Annotations Retention( RetentionPolicy.RUNTIME ) Target( ElementType.TYPE_USE, ElementType.TYPE_PARAMETER ) public interface NonEmpty public static class Holder extends NonEmpty Object public void method() throws NonEmpty Exception SuppressWarnings( unused ) public static void main(String args) final Holder holder = new NonEmpty Holder(); NonEmpty Collection strings = new ArrayList(); ElementType.TYPE_USE和ElementType.TYPE_PARAMETER是两个新添加的用于描述适当的注解上下文的元素类型。在Java语言中,注解处理API也有小的改动来识别新增的类型注解。参数名字很长一段时间里,Java程序员一直在发明不同的方式使得方法参数的名字能保留在Java字节码中,并且能够在运行时获取它们(比如,Paranamer类库)。最终,在Java 8中把这个强烈要求的功能添加到语言层面(通过反射API与Parameter.getName()方法)与字节码文件(通过新版的javac的parameters选项)中。public class ParameterNames public static void main(String args) throws Exception Method = ParameterNames.class.getMethod( main, String.class ); for( final Parameter : method.getParameters() ) System.out.println( Parameter: + parameter.getName() ); 如果不使用parameters参数来编译这个类,然后运行这个类,会得到下面的输出:Parameter: arg0如果使用parameters参数来编译这个类,程序的结构会有所不同(参数的真实名字将会显示出来):Parameter: args org.apache.maven.plugins maven-compiler-plugin 3.1 -parameters 1.8 1.8 Optional臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。更多详情请参考官方文档。Optional 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 firstName2 = Optional.of( Tom );System.out.println( First Name is set? + firstName2.isPresent() ); System.out.println( First Name: + firstName2.orElseGet( () - none ) ); System.out.println( firstName2.map( s - Hey + s + ! ).orElse( Hey Stranger! ) );StreamStream API(java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的 Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。而和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。多种方式生成 Stream Source:从 Collection 和数组Collection.stream()Collection.parallelStream()Arrays.stream(T array) or Stream.of()从 BufferedReaderjava.io.BufferedReader.lines()静态工厂java.util.stream.IntStream.range()java.nio.file.Files.walk()自己构建java.util.Spliterator其它Random.ints()BitSet.stream()Pattern.splitAsStream(java.lang.CharSequence)JarFile.stream()stream操作类型Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。还有一种操作被称为 short-circuiting。用以指:对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。实例:int sum = widgets.stream().filter(w - w.getColor() = RED).mapToInt(w - w.getWeight().sum(); stream() 获取当前小物件的 source,filter 和 mapToInt 为 intermediate 操作,进行数据筛选和转换,最后一个 sum() 为 terminal 操作,对符合条件的全部小物件作重量求和。操作类型对应的方法Intermediate类型方法:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unorderedTerminal类型方法:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iteratorShort-circuiting类型方法:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limitDate/Time APIJava 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。对日期与时间的操作一直是Java程序员最痛苦的地方之一。标准的 java.util.Date以及后来的java.util.Calendar一点没有改善这种情况(可以这么说,它们一定程度上更加复杂)。这种情况直接导致了Joda-Time一个可替换标准日期/时间处理且功能非常强大的Java API的诞生。Java 8新的Date-Time API (JSR 310)在很大程度上受到Joda-Time的影响,并且吸取了其精髓。新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。在设计新版API时,十分注重与旧版API的兼容性:不允许有任何的改变(从java.util.Calendar中得到的深刻教训)。如果需要修改,会返回这个类的一个新实例。Clock类,它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。LocaleDate与LocalTime。LocaleDate只持有ISO-8601格式且无时区信息的日期部分。相应的,LocaleTime只持有ISO-8601格式且无时区信息的时间部分。LocaleDate与LocalTime都可以从Clock中得到。特定时区的日期/时间,那么ZonedDateTime是你的选择。它持有ISO-8601格式具具有时区信息的日期与时间。Duration类:在秒与纳秒级别上的一段时间。Duration使计算两个日期间的不同变的十分简单,用于比较。并行(parallel)数组Java 8增加了大量的新方法来对数组进行并行处理。可以说,最重要的是parallelSort()方法,因为它可以在多核机器上极大提高数组排序的速度。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();Base64在Java 8中,Base64编码已经成为Java类库的标准。 Base64类同时还提供了对URL、MIME友好的编码器与解码器(Base64.getUrlEncoder() / Base64.getUrlDecoder(), Base64.getMimeEncoder() /Base64.getMimeDecoder())。实例: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!并发(Concurrency)在新增Stream机制与lambda的基础之上,在java.util.concurrent.ConcurrentHashMap中加入了一些新方法来支持聚集操作。同时也在java.util.concurrent.ForkJoinPool类中加入了一些新方法来支持共有资源池(common pool)(请查看我们关于Java 并发的免费课程)。新增的java.util.concurrent.locks.StampedLock类提供一直基于容量的锁,这种锁有三个模型来控制读写操作(它被认为是不太有名的java.util.concurrent.locks.ReadWriteLock类的替代者)。在java.util.concurrent.atomic包中还增加了下面这些类:DoubleAccumulatorDoubleAdderLongAccumulatorLongAdderJavaScript引擎NashornNashorn,一个新的JavaScript引擎随着Java 8一起公诸于世,它允许在JVM上开发运行某些JavaScript应用。Nashorn就是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.NashornScriptEngineResult: 2新的Java工具Nashorn引擎: jjsjjs是个基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码。类依赖分析器jdepsjdeps是一个很有用的命令行工具。它可以显示Java类的包级别或类级别的依赖。它接受一个.class文件,一个目录,或者一个jar文件作为输入。jdeps默认把结果输出到系统输出(控制台)上。实例:jdeps org.springframework.core-3.0.5.RELEASE.jarorg.springframework.core-3.0.5.RELEASE.jar - C:Program FilesJavajdk1.8.0jrelibrt.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 Java虚拟机(JVM)的新特性PermGen空间被移除了,取而代之的是Metaspace(JEP 122)。JVM选项-XX:PermSize与-XX:MaxPermSize分别被-XX:MetaSpaceSize与-XX:MaxMetaspaceSize所代替。
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号