zoukankan      html  css  js  c++  java
  • (转) Java 9 学习笔记 (二)

    reference

    [1] http://www.cnblogs.com/IcanFixIt/p/7278696.html

     List, Set and Map

    在Java语言中支持collection literals是非常需要的功能。 JDK 9替代了对collection literals的支持,更新了Collection API,而是在ListSetMap接口中添加了of()静态工厂方法,分别返回一个不可变的ListSetMap。该方法被重载,指定集合的​​零到十个元素。 ListSet接口提供了可变参数的of()方法,用于创建一个包含任意数量的元素的ListSet。 Map接口提供了ofEntries()静态工厂方法,用于创建一个不可变的任意数量条目的Map。 Map接口还包含一个静态的entry()方法,它接受一个键和一个值作为参数并返回一个Map.Entry实例。 ofEntries()entry()方法一起使用来创建任意数量条目的不可变的Map

    这些接口中的新的静态工厂方法为性能做了调整。 List.of()Set.of()方法不允许使用null元素。 Set.of()方法不允许重复的元素。 Map.of()Map.ofEntries()方法不允许重复键,或者将null作为键或值。

    HTTP/2 Client API

    JDK 9添加了一个HTTP/2 Client API,可以在Java应用程序中使用HTTP请求和响应。 API提供类和接口来开发具有身份验证和TLS的WebSocket客户端。 API位于jdk.incubator.http包中,该包位于jdk.incubator.httpclient模块中。

    三个抽象类,HttpClientHttpRequestHttpResponseWebSocket接口是HTTP/2 Client API的核心。这些类型的实例使用构建器创建。 HttpClient类是不可变的。HttpClient类的实例保存可以重复用于多个HTTP请求的HTTP连接配置。 HttpRequest类实例表示HTTP请求。 HttpResponse类的实例表示从服务器接收的HTTP响应。可以同步或异步地发送和接收HTTP请求和响应。

    WebSocket接口的实例表示一个WebSocket客户端endpoint。与WebSocket服务器端endpoint的通信是异步完成的。 WebSocket API是基于事件的。需要为WebSocket客户端endpoint指定一个监听器,它是WebSocket.Listener接口的一个实例。监听器通过调用其适当的方法 —— 当事件发生在endpoint上时,例如,当通过调用监听器的onOpen()方法成功完成与对等体的打开握手时,通知监听器。 API支持与对等体交换文本以及二进制消息。消息可以部分交换。

    栈遍历

    在JDK 9之前,Stack-Walking API存在以下缺点:

    • 效率不高。Throwable类的getStrackTrace()方法返回整个栈的快照。 没有办法在栈中只得到几个顶部栈帧。
    • 栈帧包含方法名称和类名称,而不是类引用。 类引用是Class<?>类的实例,而类名只是字符串。
    • JVM规范允许虚拟机实现在栈中省略一些栈帧来提升性能。 因此,如果有兴趣检查整个栈,那么如果虚拟机隐藏了一些栈帧,则无法执行此操作。
    • JDK和其他类库中的许多API都是调用者敏感(caller-sensitive)的。 他们的行为基于调用者的类而有所不同。 例如,如果要调用Module类的addExports()方法,调用者的类必须在同一个模块中。 否则,将抛出一个IllegalCallerException异常。 在现有的API中,没有简单而有效的方式来获取调用者的类引用。 这样的API依赖于使用JDK内部API —— sun.reflect.Reflection类的getCallerClass()静态方法。
    • 没有简单的方法来过滤特定实现类的栈帧。

    JDK 9引入了一个新的Stack-Walking API,它由java.lang包中的StackWalker类组成。 该类提供简单而有效的栈遍历。 它为当前线程提供了一个顺序的栈帧流。 从栈生成的最上面的到最下面的栈帧,栈帧按顺序记录。 StackWalker类非常高效,因为它可以懒加载的方式地评估栈帧。 它还包含一个便捷的方法来获取调用者类的引用。 StackWalker类由以下成员组成:

    • StackWalker.Option嵌套枚举
    • StackWalker.StackFrame嵌套接口
    • 获取StackWalker类实例的方法
    • 处理栈帧的方法
    • 获取调用者类的方法

    在JDK 9之前,StackTraceElement类的实例被用来表示栈帧。 JDK 9中的Stack-Walker API使用StackWalker.StackFrame接口的实例来表示栈帧。

    Tips
    StackWalker.StackFrame接口没有具体的实现类,可以直接使用。 JDK中的Stack-Walking API在检索栈帧时为你提供了接口的实例。

    以下代码片段使用walk()方法遍历整个栈,打印每个栈帧的详细信息。 这段代码与前面的代码片段使用forEach()方法相同。

    // Prints the details of all stack frames of the current thread
    StackWalker.getInstance()
               .walk(s -> {
                   s.forEach(System.out::println);
                   return null;
                });

    Tips
    StackWalker的forEach()方法用于一次处理一个栈帧,而walk()方法用于处理将整个栈为帧流。 可以使用walk()方法来模拟forEach()方法的功能,但反之亦然

    在JDK 9之前,开发人员依靠以下方法来获取调用者的调用:

    • SecurityManager类的getClassContext()方法,由于该方法受到保护,因此需要进行子类化。
    • sun.reflect.Reflection类的getCallerClass()方法,它是一个JDK内部类。

    JDK 9通过在StackWalker类中添加一个getCallerClass()的方法,使得获取调用者类引用变得容易。 方法的返回类型是Class<?>。 如果StackWalker未配置RETAIN_CLASS_REFERENCE选项,则调用此方法将抛出UnsupportedOperationException异常。 如果栈中没有调用者栈帧,则调用此方法会引发IllegalStateException,例如,运行main()方法调用此方法的类。

    那么,哪个类是调用类? 在Java中,方法和构造函数可调用。 以下讨论使用方法,但是它也适用于构造函数。 假设在S的方法中调用getCallerClass()方法,该方法从T的方法调用。另外假设T的方法在名为C的类中。在这种情况下,C类是调用者类。

    Tips
    StackWalker类的getCallerClass()方法在查找调用者类时会过滤所有隐藏和反射栈帧,而不管用于获取StackWalker实例的选项如何。

    流 Stream

    流是由生产者生产并由一个或多个消费者消费的元素(item)的序列。 这种生产者——消费者模型也被称为source/sink模型或发布者——订阅者(publisher-subscriber )模型。 在本章中,将其称为发布者订阅者模型。

    Reactive Stream 响应式流从2013年开始,作为提供非阻塞背压的异步流处理标准的倡议。 它旨在解决处理元素流的问题——如何将元素流从发布者传递到订阅者,而不需要发布者阻塞,或订阅者有无限制的缓冲区或丢弃.

    Java API 的响应式流只包含四个接口:

    Publisher<T>
    Subscriber<T>
    Subscription
    Processor<T,R>

    发布者(publisher)是潜在无限数量的有序元素的生产者。 它根据收到的要求向当前订阅者发布(或发送)元素。

    订阅者(subscriber)从发布者那里订阅并接收元素。 发布者向订阅者发送订阅令牌(subscription token)。 使用订阅令牌,订阅者从发布者哪里请求多个元素。 当元素准备就绪时,发布者向订阅者发送多个或更少的元素。 订阅者可以请求更多的元素。 发布者可能有多个来自订阅者的元素待处理请求。

    订阅(subscription)表示订阅者订阅的一个发布者的令牌。 当订阅请求成功时,发布者将其传递给订阅者。 订阅者使用订阅令牌与发布者进行交互,例如请求更多的元素或取消订阅。

    处理者(processor)充当订阅者和发布者的处理阶段。 Processor接口继承了PublisherSubscriber接口。 它用于转换发布者——订阅者管道中的元素。 Processor<T,R>订阅类型T的数据元素,接收并转换为类型R的数据,并发布变换后的数据。 下图显示了处理者在发布者——订阅和管道中作为转换器的作用。 可以拥有多个处理者。

    JDK 9在java.util.concurrent包中提供了一个与响应式流兼容的API,它在java.base模块中。 API由两个类组成:

    Flow
    SubmissionPublisher<T>

    Flow类是final的。 它封装了响应式流Java API和静态方法。 由响应式流Java API指定的四个接口作为嵌套静态接口包含在Flow类中:

    Flow.Processor<T,R>
    Flow.Publisher<T>
    Flow.Subscriber<T>
    Flow.Subscription

    这四个接口包含与上面代码所示的相同的方法。 Flow类包含defaultBufferSize()静态方法,它返回发布者和订阅者使用的缓冲区的默认大小。 目前,它返回256。

    SubmissionPublisher<T>类是Flow.Publisher<T>接口的实现类。 该类实现了AutoCloseable接口,因此可以使用try-with-resources块来管理其实例。 JDK 9不提供Flow.Subscriber<T>接口的实现类; 需要自己实现。 但是,SubmissionPublisher<T>类包含可用于处理此发布者发布的所有元素的consume(Consumer<? super T> consumer)方法。

    Stream new API

    JDK 9向Streams API添加了一些便利的方法,使流处理更容易,并使用收集器编写复杂的查询。

    Stream接口有四种新方法:dropWhile()),takeWhile()ofNullable()iterate()。对于有序流,dropWhile()方法返回流的元素,从指定predicate为true的起始处丢弃元素。对于无序流,dropWhile()方法的行为是非确定性的。它可以选择删除匹配predicate的任何元素子集。当前的实现从匹配元素开始丢弃匹配元素,直到找到不匹配的元素。 takeWhile()方法的工作方式与dropWhile()方法相同,只不过它从流的起始处返回匹配的元素,而丢弃其余的。如果元素为非空,则Nullable(T t)方法返回包含指定元素的单个元素的流。如果指定的元素为空,则返回一个空的流。新的iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)方法允许使用初始种子值创建顺序(可能是无限)流,并迭代应用指定的下一个方法。当指定的hasNextpredicate返回false时,迭代停止。

    Collectors类在JDK 9中有两种新方法:filtering()flatMapping()。 filtering()方法返回在收集元素之前应用过滤器的收集器。如果指定的predicate对于元素返回true,则会收集元素;否则,元素未被收集。 flatMapping()方法返回在收集元素之前应用扁平映射方法的收集器。指定的扁平映射方法被应用到流的每个元素,并且从扁平映射器返回的流的元素的累积。

    在JDK 9中,下划线(_)是一个关键字,不能将其本身用作单字符标识符,例如变量名称,方法名称,类型名称等。但是,仍然可以使用下划线多个字符的标识符名称。

    JDK 9删除了限制,必须使用try-with-resource块为要管理的资源声明新变量。现在,可以使用final或有效的final变量来引用资源由try-with-resources块来管理。

    只要推断的类型是可表示的,JDK 9就添加了对匿名类中的钻石操作符的支持。

    可以在接口中具有非抽象非默认实例方法或静态方法的私有方法。

    JDK 9允许在私有方法上使用@SafeVarargs注解。 JDK 8已经允许它在构造方法,stati方法和final`方法上。

    JDK 9向ProcessBuilder.Redirect嵌套类添加了DISCARD的新常量。它的类型是ProcessBuilder.Redirect。当要丢弃输出时,可以将其用作子进程的输出和错误流的目标。实现通过写入操作系统特定的“空文件”来丢弃输出。

    JDK 9为MathStrictMath类添加了几种方法来支持更多的数学运算,如floorDiv(long x, int y)floorMod(long x, int y)multiplyExact(long x, int y)multiplyFull(int x, int y)multiplyHigh(long x, long y) 等。

    JDK 9向java.util.Optional类添加了三个方法:ifPresentOrElse()of()stream()。 ifPresentOrElse()方法可以提供两个备选的操作。如果存在值,则执行一个操作。否则,它执行另一个操作。如果存在值,则or()方法返回Optional。否则返回指定Supplier返回的可选项。 stream()方法返回包含可选中存在的值的元素的顺序流。如果Optional为空,则返回一个空的流。 stream()方法在扁平映射中(flat maps)很有用。

    JDK 9向Thread类添加了一个新的静态onSpinWai()方法。对处理器来说,这是一个纯粹的提示,即调用者线程暂时无法继续,因此可以优化资源使用。在自旋循环中使用它。

    Time API在JDK 9中得到了一个提升。在DurationLocalDateLocalTimeOffsetTime类中添加了几种方法。LocalDate类接收到一个新的datesUntil()方法,它返回两个日期之间的日期流,以一天或给定期间的增量。 Time API中有几个新的格式化符号。

    Matcher类新增几个现有方法的重载版本,它们用于与StringBuffer一起工作,以支持使用StringBuilder。一个为results()的新方法返回一个Stream<MatchResult>。 Objects类收到了几个新的实用方法来检查数组和集合的范围。

    ava.util.Arrays新增了几种方法,可以比较数组和部分数组的相等性和不匹配性。

    Javadoc在JDK 9中得到了增强。它支持HTML5。可以使用一个新的选项-html5与javadoc工具一起生成HTML5格式的Javadoc。对所有模块,包,类型,成员和形式参数类型的名称进行索引,并使用新的搜索功能进行搜索。 Javadoc在每个主页的右上角显示一个搜索框,可用于搜索索引条款。还可以在Javadoc中使用一个新的标签@index来创建用户定义的术语。使用客户端JavaScript执行搜索,并且不进行服务器通信。

    许多浏览器供应商已经删除了对Java浏览器插件的支持,或者将在不久的将来删除它。记住这一点,JDK 9不赞成使用Applet API。 java.applet包和javax.swing.JApplet类中的所有类型已被弃用。 appletviewer工具也已被弃用。

    JDK 6通过java.awt.Desktop类添加了对平台特定桌面功能的有限支持,例如在用户默认浏览器中打开URI,在用户默认邮件客户端中打开mailto URI,以及使用注册的应用打开,编辑和打印文件。如果Java SE 9在当前平台上可用,许多系统和应用程序事件通知都会提供特定于平台的桌面支持,并为其添加了公共API支持。为了支持这么多新的桌面功能,Java SE 9向java.desktop模块添加了一个新的包java.awt.desktop。 java.awt.Desktop类也增加了很多新的方法。在JDK 9中,Desktop API支持24个平台特定的桌面操作和通知,例如当附加的显示进入或退出节电模式,系统进入睡眠模式或系统唤醒后的通知等。
    为了解决反序列化带来的安全风险,JDK 9引入了一个对象输入过滤器的概念,可以用来验证被反序列化的对象,如果没有通过测试,则可以停止反序列化过程。对象输入过滤器是新接口java.io.ObjectInputFilter的实例。可以指定可以在反序列化任何对象时使用的全系统全局过滤器。可以使用新的jdk.serialFilter系统属性,使用JAVA_HOMEconfsecurityjava.security文件中jdk.serialFilter的属性,或使用ObjectInputFilter.Config类的setSerialFilter()方法来指定全局过滤器。可以使用其setObjectInputFilter()方法在ObjectInputStream上设置本地过滤器,该方法将覆盖全局过滤器。

    java.io.InputStream类新增一个称为transferTo(OutputStream out)的方法,可用于从输入流读取所有字节,并将它们顺序写入指定的输出流。该方法不关闭任一流。 java.nio.Buffer类接收到两个方法,duplicate()slice()——可用于复制和拼接缓冲区。复制和分片缓冲区与原始缓冲区共享其内容。但是他们保持自己的位置,限定和标记,独立于原始缓冲区。

  • 相关阅读:
    散列算法
    【转】认证 (authentication) 和授权 (authorization) 的区别
    Filter和interceptor比较
    【转】深入理解Spring的两大特征(IOC和AOP)
    [转]web.xml中servlet ,filter ,listener ,interceptor的作用与区别
    线程同步
    Java容器
    进程间交互的几种方式
    JSP和Servlet的区别
    IPC介绍
  • 原文地址:https://www.cnblogs.com/codingforum/p/9065547.html
Copyright © 2011-2022 走看看