JDK9新特性

JDK9新特性:

    1.模块系统

    2.JShell和Jlink

    3.不可变集合类工厂方法

    4.接口中的私有方法

    5.一些改进的API

    6.try-with-resources改进

    7.HTTP2支持

    8.平台日志API和服务

    9.垃圾回收器

    10.增加加密算法

 

 

    一、Java 平台级模块系统

    Java 9 新特性中最大的一个变化就是 Module System。JDK 9包含有 92 个 modules(当然也可能在最终发布版中有所变化)。我们可以使用 JDK Modules,也能创建我们自己的 modules,如:module com.foo.bar { }。这里我们使用 module 关键字创建了一个简单的 module。每个 module 都有一个名字,对应代码和其它一些资源。

    模块化-以 Java 平台模块系统的形式-将 JDK 分成一组模块,可以在运行时,编译时或者构建时进行组合。模块化被称为一个“可传递”的更改,它支持对模块间依赖的理解。

    Java 9 的模块化能让开发者更容易的组合和维护复杂的应用程序。同时,它也使 Java 在改进安全和性能的同时能够更好的适配到更小的设备中。

    Java 9 的模块化包含应用打包,JDK 自身模块化,以及将源码重新组织成多个模块。构建系统在构建时编译模块和识别模块边界的能力也得到增强。JDK 和 Java 运行时环境(JRE)的镜像经过重构以处理模块化。

    Java 9 的定义功能是一套全新的模块系统。当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。这时候就得面对两个基础的问题: 很难真正地对代码进行封装, 而系统并没有对不同部分(也就是 JAR 文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到, 这样就会导致无意中使用了并不想被公开访问的 API。此外,类路径本身也存在问题: 你怎么知晓所有需要的 JAR 都已经有了, 或者是不是会有重复的项呢? 模块系统把这俩个问题都给解决了。

    模块化的 JAR 文件都包含一个额外的模块描述器。在这个模块描述器中, 对其它模块的依赖是通过 “requires” 来表示的。另外, “exports” 语句控制着哪些包是可以被其它模块访问到的。所有不被导出的包默认都封装在模块的里面。如下是一个模块描述器的示例,存在于 “module-info.java” 文件中:

    module blog {

       exports com.pluralsight.blog;

       requires cms;

    }

 

我们可以如下展示模块:

JDK9新特性_第1张图片

 

    请注意,两个模块都包含封装的包,因为它们没有被导出(使用橙色盾牌可视化)。 没有人会偶然地使用来自这些包中的类。Java 平台本身也使用自己的模块系统进行了模块化。通过封装 JDK 的内部类,平台更安全,持续改进也更容易。

    当启动一个模块化应用时, JVM 会验证是否所有的模块都能使用,这基于 `requires` 语句——比脆弱的类路径迈进了一大步。模块允许你更好地强制结构化封装你的应用并明确依赖。你可以在这个课程中学习更多关于 Java 9 中模块工作的信息 。

 

 

 

    二、Linking和JShell

    JLink:当你使用具有显式依赖关系的模块和模块化的 JDK 时,新的可能性出现了。你的应用程序模块现在将声明其对其他应用程序模块的依赖以及对其所使用的 JDK 模块的依赖。为什么不使用这些信息创建一个最小的运行时环境,其中只包含运行应用程序所需的那些模块呢? 这可以通过 Java 9 中的新的 jlink 工具实现。你可以创建针对应用程序进行优化的最小运行时映像而不需要使用完全加载 JDK 安装版本。

 

    JShell:java已经具有交互式编程环境,JShelll是一种快速运行语句的命令行工具。现在可以从控制台启动 jshell ,并直接启动输入和执行 Java 代码。 jshell 的即时反馈使它成为探索 API 和尝试语言特性的好工具。

JDK9新特性_第2张图片

 

    测试一个 Java 正则表达式是一个很好的说明 jshell 如何使您的生活更轻松的例子。 交互式 shell 还可以提供良好的教学环境以及提高生产力,您可以在此了解更多信息。在教人们如何编写 Java 的过程中,不再需要解释 “public static void main(String [] args)” 这句废话。

 

 

    三、集合工厂方法

    通常,可能会在代码中创建一个集合(例如List 或 Set ),并直接用一些元素填充它,所以在实例化集合通过几个add()调用使得代码重复。同时在JavaSE 8和更早版本中,我们常用类似 unmodifiableXXX 的集合类方法创建不可变集合对象。举个例子,比如我们想创建一个不可变的 List 对象,可能使用到 Collections.unmodifiableList 方法。然而,这些 Collections.unmodifiableXXX 方法显得非常冗长乏味。为了克服这些缺陷,Oracle 公司给 List、Set 和 Map 接口分别添加了两个更加实用的方法。List 和 Set 接口使用 of() 方法创建一个空或者非空的不可变 List 或 Set 对象。

    Set ints = Set.of(1, 2, 3);

    List strings = List.of("first", "second");

    所以这样解决了两个问题一个是繁琐的填充过程另一个是更方便的创建不可变集合。工厂方法返回已放入数个元素的集合实现是高度优化的同时通过工厂方式创建的集合就会成为不可变集合,在创建后,继续添加元素到这些集合会导致 “UnsupportedOperationException” 。

 

    四、接口中的私有方法

    在Java 8中,我们可以在接口中使用默认或者静态方法提供一些实现方式,但是不能创建私有方法。 但是如果在接口上有几个默认方法,代码几乎相同,通常会将这些方法进行重构,调用一个可复用的私有方法。 但默认方法不能是私有的。 将复用代码创建为一个默认方法不是一个解决方案,因为该辅助方法会成为公共API的一部分。 为了避免冗余代码和提高重用性,Oracle 公司在 Java 9 接口中引入私有方法,可以在接口中添加私有辅助方法来解决此问题。

    也就是说从 Java 9 开始,我们也能够在接口类中使用 ‘private’ 关键字写私有化方法和私有化静态方法。接口中的私有方法与 class 类中的私有方法在写法上并无差异,如:

    public interface Card{

      private Long createCardID(){

        // Method implementation goes here.

     }

      private static void displayCardDetails(){

        // Method implementation goes here.

      }

   }

 

 

    五、进程API的改进

    Java 9 迎来一些 Process API 的改进,通过添加一些新的类和方法来优化系统级进程的管控。Process API 中的两个新接口:

       1.java.lang.ProcessHandle

       2.java.lang.ProcessHandle.Info

 

    Process API 示例:

    ProcessHandle currentProcess = ProcessHandle.current();

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

 

    六、Try-With-Resources 改进

    Java 7 引入了一个新的异常处理结构:Try-With-Resources,来自动管理资源。try-with-resources语句是一种声明了一种或多种资源的try语句。资源是指在程序用完了之后必须要关闭的对象。try-with-resources语句保证了每个声明了的资源在语句结束的时候都会被关闭。任何实现了java.lang.AutoCloseable接口的对象,和实现了java.io.Closeable接口的对象,都可以当做资源使用。这个新的声明结构主要目的是实现“Automatic Better Resource Management”(“自动资源管理”)。

    Java 9 将对这个声明作出一些改进来避免一些冗长写法,同时提高可读性。

    Java 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());

        }

    }

 

    七、HTTP/2

    在 Java 9 中,Oracle 公司发布新的HTTP2 Client API来支持 HTTP/2 协议和 WebSocket 特性。有新的方式来处理 HTTP 调用。老版本的HTTP Client API存在很多问题(如支持 HTTP/1.1 协议但是不支持 HTTP/2 协议和 WebSocket,仅仅作用在 Blocking 模式中,并存在大量性能问题),他们正在被使用新的 HTTP 客户端的 HttpURLConnection API 所替代这个迟到的特性用于代替老旧的 HttpURLConnection API,并提供对 WebSocket 和 HTTP/2 的支持。注意:新的 HttpClient API 在 Java 9 中以所谓的孵化器模块交付。也就是说,这套 API 不能保证 100% 完成。不过你可以在 Java 9 中开始使用这套 API:

    HttpClient client = HttpClient.newHttpClient(); 

    HttpRequest req = HttpRequest.newBuilder(URI.create("http://www.google.com")).header("User-Agent","Java").GET().build();

    HttpResponse resp = client.send(req, HttpResponse.BodyHandler.asString());

    HttpResponse resp = client.send(req, HttpResponse.BodyHandler.asString());

    除了这个简单的请求/响应模型之外,HttpClient 还提供了新的 API 来处理 HTTP/2 的特性,比如流和服务端推送。

 

    八、一些改进的API

    1.改进的平台的日志API

    Java 9 中 ,JVM 有了统一的日志记录系统,可以使用新的命令行选项-Xlog 来控制 JVM 上 所有组件的日志记录。该日志记录系统可以设置输出的日志消息的标签、级别、修饰符和输出目标等。

    Java 9 允许为 JDK 和应用配置同样的日志实现。新增的 System.LoggerFinder 用来管理 JDK 使 用的日志记录器实现。JVM 在运行时只有一个系统范围的 LoggerFinder 实例。LoggerFinder 通 过服务查找机制来加载日志记录器实现。默认情况下,JDK 使用 java.logging 模块中的 java.util.logging 实现。通过 LoggerFinder 的 getLogger()方法就可以获取到表示日志记录器的 System.Logger 实现。应用同样可以使用 System.Logger 来记录日志。这样就保证了 JDK 和应用使用同样的日志实现。我们也可以通过添加自己的 System.LoggerFinder 实现来让 JDK 和应用使用 SLF4J 等其他日志记录框架。 代码清单 9 中给出了平台日志 API 的使用示例。

    使用平台日志 API:

    private static final System.Logger LOGGER = System.getLogger("Main");

    public static void main(final String[] args) {

        LOGGER.log(Level.INFO, "Run!");

    }

    2.改进的 Stream API

    Stream API 是Java标准库最好的改进之一。通过这套 API 可以在集合上建立用于转换的管道。Stream 接口中添加了 4 个新的方法:dropWhile, takeWhile, ofNullable。还有个 iterate 方法的新重载方法,可以你提供一个 Predicate (判断条件)来指定什么时候结束迭代:

    IntStream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);

    第二个参数是一个 Lambda,它会在当前 IntStream 中的元素到达 100 的时候返回 true。因此这个简单的示例是向控制台打印 1 到 99。

    除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。现在可以通过 Optional 的新方法 `stram` 将一个 Optional 对象转换为一个(可能是空的) Stream 对象:Stream s = Optional.of(1).stream();。在组合复杂的 Stream 管道时,将 Optional 转换为 Stream 非常有用。

 

    九、垃圾回收器

    JDK1.8 默认垃圾收集器是Parallel,Java 9 移除了在 Java 8 中 被废弃的垃圾回收器配置组合,同时 把 G1 设为默认的垃圾回收器实现。另外,CMS 垃圾回收器已经被声明为废弃。

 

 

    十、增加加密算法

    Java 9 新增了 4 个 SHA- 3 哈希算法,SHA3-224、SHA3-256、SHA3-384 和 S HA3-512。另外也增加了通过 java.security.SecureRandom 生成使用 DRBG 算法的强随机数。 代码清单 13 中给出了 SHA-3 哈希算法的使用示例:

    public static void main(final String[] args) throws NoSuchAlgorithmException {

        final MessageDigest instance = MessageDigest.getInstance("SHA3-224");

        final byte[] digest = instance.digest("".getBytes());

        System.out.println(Hex.encodeHexString(digest));

    }

你可能感兴趣的:(Java)