Java 9 特性与示例

Java 9 是一个重要的版本,为开发者带来了许多新特性。在这篇文章中,我们将详细介绍 Java 9 的特性。

Java 10 已经发布,要了解 Java 10 发布的完整概述,请查看 Java 10 特性

Java 9 特性

一些重要的 Java 9 特性包括;

  1. Java 9 REPL(JShell)
  2. 不可变列表、集合、映射和映射条目的工厂方法
  3. 接口中的私有方法
  4. Java 9 模块系统
  5. 进程 API 改进
  6. 改进的资源管理
  7. CompletableFuture API 改进
  8. 响应式流
  9. 匿名内部类的钻石操作符
  10. Optional 类改进
  11. 流 API 改进
  12. 增强的 @Deprecated 注解
  13. HTTP 2 客户端
  14. 多分辨率图像 API
  15. 杂项 Java 9 特性

Oracle 公司计划在 2017 年 3 月底左右发布 Java SE 9。在本文中,我将简要讨论一些“Java 9 特性”,并附带一些示例。

Java 9 REPL (JShell)

Oracle 公司推出了一个名为“jshell”的新工具。它代表 Java Shell,也被称为 REPL(Read Evaluate Print Loop)。它用于非常轻松地执行和测试任何 Java 构造,如类、接口、枚举、对象、语句等。我们可以从 https://jdk9.java.net/download/ 下载 JDK 9 EA(早期访问)软件。

G:\>jshell
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro


jshell> int a = 10
a ==> 10

jshell> System.out.println("a value = " + a )
a value = 10

如果您想了解更多关于 REPL 工具的信息,请阅读 Java 9 REPL 基础知识(第一部分)Java 9 REPL 特性(第二部分)

Immutable List、Set、Map 和 Map.Entry 的工厂方法

Oracle 公司推出了一些方便的工厂方法,用于创建不可变的 List、Set、Map 和 Map.Entry 对象。这些实用方法用于创建空的或非空的集合对象。在 Java SE 8 及之前的版本中,我们可以使用 Collections 类的实用方法,比如 unmodifiableXXX 来创建不可变的集合对象。例如,如果我们想创建一个不可变的 List,那么我们可以使用 Collections.unmodifiableList 方法。然而,这些 Collections.unmodifiableXXX 方法是一种繁琐而冗长的方法。为了克服这些缺点,Oracle 公司在 List、Set 和 Map 接口中添加了一些实用方法。List 和 Set 接口有 “of()” 方法,用于创建空的或非空的不可变 List 或 Set 对象,如下所示:空 List 示例

List immutableList = List.of();

非空 List 示例

List immutableList = List.of("one","two","three");

Map 有两组方法:of() 方法和 ofEntries() 方法,分别用于创建不可变的 Map 对象和不可变的 Map.Entry 对象。空 Map 示例

jshell> Map emptyImmutableMap = Map.of()
emptyImmutableMap ==> {}

非空 Map 示例

jshell> Map nonemptyImmutableMap = Map.of(1, "one", 2, "two", 3, "three")
nonemptyImmutableMap ==> {2=two, 3=three, 1=one}

如果您想了解更多关于这些实用方法的信息,请参阅以下链接:

接口中的私有方法

在Java 8中,我们可以使用默认方法和静态方法在接口中提供方法实现。然而,我们无法在接口中创建私有方法。为了避免冗余代码并提高可重用性,Oracle公司将在Java SE 9接口中引入私有方法。从Java SE 9开始,我们可以使用’private’关键字在接口中编写私有和私有静态方法。这些私有方法与其他类的私有方法一样,它们之间没有区别。

public interface Card{

  private Long createCardID(){
    // 方法实现在这里。
  }

  private static void displayCardDetails(){
    // 方法实现在这里。
  }

}

如果您想了解更多关于这一新功能的信息,请阅读此链接:Java 9 接口中的私有方法

Java 9 模块系统

Java 9 的一个重大变化或特性是模块系统。Oracle公司将引入以下特性作为拼图项目的一部分。

  • 模块化JDK
  • 模块化Java源代码
  • 模块化运行时镜像
  • 封装Java内部APIs
  • Java平台模块系统

在Java SE 9版本之前,我们使用单体Jars来开发基于Java的应用程序。这种架构有很多限制和缺点。为了避免所有这些缺点,Java SE 9带来了模块系统。JDK 9带来了92个模块(在最终发布中可能会有变化)。我们可以使用JDK模块,也可以像下面显示的那样创建我们自己的模块:简单模块示例

module com.foo.bar { }

这里我们使用‘module’来创建一个简单的模块。每个模块都有一个名称、相关代码和其他资源。要了解更多关于这种新架构的详细信息和实践经验,请阅读我这里的原始教程:

进程API改进

Java SE 9带来了一些进程API的改进。他们添加了一些新的类和方法,以便更轻松地控制和管理操作系统进程。进程API中的两个新接口:

进程API示例

 ProcessHandle currentProcess = ProcessHandle.current();
 System.out.println("Current Process Id: = " + currentProcess.getPid());

Try With Resources改进

我们知道,Java SE 7引入了一个新的异常处理结构:Try-With-Resources,用于自动管理资源。这个新语句的主要目标是“自动更好的资源管理”。Java SE 9将对这个语句进行一些改进,以避免更多的冗余,并提高一些可读性。Java SE 7示例

void testARM_Before_Java9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (BufferedReader reader2 = reader1) {
   System.out.println(reader2.readLine());
 }
}

Java 9示例

void testARM_Java9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (reader1) {
   System.out.println(reader1.readLine());
 }
}

阅读有关这个新功能的更多信息,请查看我的原始教程:Java 9中的Try-With-Resources改进

CompletableFuture API改进

在Java SE 9中,Oracle Corp将改进CompletableFuture API以解决Java SE 8中提出的一些问题。他们将添加对一些延迟和超时的支持,一些实用方法和更好的子类化。

Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);

这里的delayedExecutor()是一个静态实用方法,用于在给定的延迟之后将任务提交给默认执行程序。

响应式流

如今,响应式编程在开发应用程序中变得非常流行,以获得一些美好的优势。Scala、Play、Akka等框架已经集成了Reactive Streams,并获得了许多好处。Oracle Corps还在Java SE 9中引入了新的Reactive Streams API。Java SE 9 Reactive Streams API是一个发布/订阅框架,可使用Java语言非常轻松地实现异步、可伸缩和并行应用程序。Java SE 9引入了以下API,用于在基于Java的应用程序中开发Reactive Streams。

  • java.util.concurrent.Flow
  • java.util.concurrent.Flow.Publisher
  • java.util.concurrent.Flow.Subscriber
  • java.util.concurrent.Flow.Processor

阅读更多关于Java 9 Reactive Streams

匿名内部类的钻石操作符

我们知道,Java SE 7引入了一个新特性:钻石操作符,以避免冗余代码和冗长,提高可读性。然而,在Java SE 8中,Oracle公司(Java库开发者)发现了在使用匿名内部类时钻石操作符存在一些限制。他们已经修复了这些问题,并打算将它们作为Java 9的一部分发布。

  public List getEmployee(String empid){
     // 从数据存储中获取员工详细信息的代码
     return new List(emp){ };
  }

这里我们只使用了“List”而没有指定类型参数。

Optional类的改进

在Java SE 9中,Oracle公司已经向java.util.Optional类中添加了一些有用的新方法。这里我将讨论其中一个方法,并附上一个简单的例子:stream方法。如果给定Optional对象中存在一个值,则stream()方法将返回一个包含该值的顺序流。否则,它将返回一个空流。他们已经添加了“stream()”方法以便在Optional对象上懒惰地工作,如下所示:

Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)

这里Optional.stream()方法用于将一个Optional对象流转换为一个Employee对象流,以便我们可以在结果代码中懒惰地处理这个结果。要了解更多关于这一功能的信息,以及Optional类中添加的更多新方法的例子,请阅读我原始教程中的内容:Java SE 9: Optional类改进

Stream API 改进

在Java SE 9中,Oracle Corp已向java.util.Stream接口添加了四个有用的新方法。由于Stream是一个接口,所有这些新实现的方法都是默认方法。其中两个非常重要:dropWhile和takeWhile方法。如果您熟悉Scala语言或任何函数式编程语言,您肯定会了解这些方法。这些方法在编写一些函数式风格代码时非常有用。让我们在这里讨论takeWhile实用方法。takeWhile()方法将一个谓词作为参数,并返回给定Stream值的子集流,直到该谓词第一次返回false为止。如果第一个值不满足该谓词,它将返回一个空的Stream。

jshell> Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 5 )
                 .forEach(System.out::println);
1
2
3
4

要了解更多关于takeWhile和dropWhile方法以及其他新方法的信息,请阅读我原始教程中的内容:Java SE 9:Stream API改进

增强@Deprecated注释

在Java SE 8及之前的版本中,@Deprecated注解只是一个没有任何方法的标记接口。它用于标记Java API,即类、字段、方法、接口、构造函数、枚举等。在Java SE 9中,Oracle Corp已经增强了@Deprecated注解,以提供关于废弃API的更多信息,并提供了一个工具来分析应用程序对废弃API的静态使用情况。他们向这个Deprecated接口添加了两个方法:forRemovalsince来提供这些信息。

HTTP 2 客户端

在Java SE 9中,Oracle Corp将发布新的HTTP 2 Client API,以支持HTTP/2协议和WebSocket功能。由于现有的或遗留的HTTP Client API存在许多问题(如支持HTTP/1.1协议,不支持HTTP/2协议和WebSocket,在阻塞模式下工作且存在许多性能问题),因此他们正在用新的HTTP客户端替换这个HttpURLConnection API。他们将在“java.net.http”包下引入一个新的HTTP 2 Client API。它支持HTTP/1.1和HTTP/2协议。它支持同步(阻塞模式)和异步模式。它使用WebSocket API支持异步模式。我们可以在https://download.java.net/java/jdk9/docs/api/java/net/http/package-summary.html看到这个新的API。HTTP 2 Client示例

jshell> import java.net.http.*

jshell> import static java.net.http.HttpRequest.*

jshell> import static java.net.http.HttpResponse.*

jshell> URI uri = new URI("https://rams4java.blogspot.co.uk/2016/05/java-news.html")
uri ==> https://rams4java.blogspot.co.uk/2016/05/java-news.html

jshell> HttpResponse response = HttpRequest.create(uri).body(noBody()).GET().response()
response ==> java.net.http.HttpResponseImpl@79efed2d

jshell> System.out.println("Response was " + response.body(asString()))

请查看我的原始教程:Java SE 9:HTTP 2 Client 以了解HTTP/2协议和WebSocket,新API的优势以及旧API的缺点,并附有一些有用的示例。

多分辨率图像API

在Java SE 9中,Oracle Corp将引入一个新的多分辨率图像API。此API中的重要接口是MultiResolutionImage。它位于java.awt.image包中。MultiResolutionImage封装了一组具有不同高度和宽度(即不同分辨率)的图像,并允许我们根据需要查询它们。

Java 9其他功能

在这一节中,我将列出一些Java SE 9的其他功能。我并不是说这些功能不重要。它们同样重要且有用,需要通过一些有用的例子来深入了解它们。截至目前,我还没有足够的关于这些功能的信息。这就是为什么我要在这里列出它们以便简要理解。我会逐一选取这些功能,然后在上面的章节中加上简要的讨论和示例。最后会写一个单独的教程。

  • GC(垃圾收集器)改进
  • Stack-Walking API
  • 过滤传入序列化数据
  • 弃用Applet API
  • 字符串拼接优化
  • 增强的方法句柄
  • Java平台日志记录API和服务
  • 紧凑字符串
  • Nashorn解析器API
  • Javadoc搜索
  • HTML5 Javadoc

I will pickup these java 9 features one by one and update them with enough description and examples. That’s all about Java 9 features in brief with examples.

Source:
https://www.digitalocean.com/community/tutorials/java-9-features-with-examples