4年前 (2021-01-27)  Java系列 |   抢沙发  303 
文章评分 1 次,平均分 5.0

Java9的新特性

Java9概述

Java9具有丰富的特性集。虽然没有新的语言概念,但是新的api和诊断命令肯定会引起开发人员的兴趣。

在本文中,我们将对一些新特性进行快速、高层次的研究;这里提供了新特性的完整列表。

模块化系统——Jigsaw项目

让我们从一个大问题开始——将模块化引入Java平台。

模块化系统提供类似于OSGi框架系统的功能。模块具有依赖性的概念,可以导出公共API并保持实现细节隐藏/私有。

这里的主要动机之一是提供模块化JVM,它可以在可用内存少得多的设备上运行。JVM只能运行应用程序所需的那些模块和api。有关这些模块的说明,请查看此链接

另外,JVM内部(实现)api像com.sun.*无法再从应用程序代码访问。

简单地说,这些模块将在一个名为module的文件中module-info.java位于java代码层次结构的顶部:

module com.baeldung.java9.modules.car {
    requires com.baeldung.java9.modules.engines;
    exports com.baeldung.java9.modules.car.handling;
}

我们的模块需要模块引擎运行,并出口一个处理包。

有关更深入的示例,请查看OpenJDK项目Jigsaw:modulesystem快速入门指南

一个新的HTTP客户端

期待已久的旧HttpURLConnection的替代品。

新的API位于java.net.http包裹。

它应该同时支持HTTP/2协议和WebSocket握手,性能应该与apache http client、Netty和Jetty相当。

让我们通过创建和发送一个简单的HTTP请求来看看这个新功能。

更新:HTTP客户机JEP正在被移动到孵化器模块,因此它在包中不再可用java.net.http而是在jdk.incubator.http.

快速获取请求

API使用了生成器模式,这使得它非常易于快速使用:

HttpRequest request = HttpRequest.newBuilder()
  .uri(new URI("http://postman-echo.com/get"))
  .GET()
  .build();

HttpResponse<String> response = HttpClient.newHttpClient()
  .send(request, HttpResponse.BodyHandler.asString());

进程 API

为控制和管理操作系统进程,对processapi进行了改进。

进程信息

java.lang.ProcessHandle文件包含大多数新功能:

ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();
 
Optional<String[]> args = procInfo.arguments();
Optional<String> cmd =  procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();

current方法返回一个表示当前运行JVM的进程的对象。Info子类提供了有关进程的详细信息。

销毁进程

现在–让我们使用destroy()停止所有正在运行的子进程:

childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
    assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});

其他的语言改进

Try-With-Resources

在Java7中,try with resources语法要求为语句管理的每个资源声明一个新的变量。

在Java 9中还有一个额外的优化:如果资源由final或final变量引用,try with resources语句可以管理资源,而不必声明新变量:

MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
    // do some stuff with mac
}
 
try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
   // do some stuff with finalCloseable
} catch (Exception ex) { }

Diamond运算符扩展

现在我们可以将Diamond运算符与匿名内部类结合使用:

FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
};
 
FooClass<? extends Integer> fc0 = new FooClass<>(1) { 
    // anonymous inner class
};
 
FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
};

接口私有方法

即将发布的JVM版本中的接口可以具有私有方法,这些方法可用于拆分冗长的默认方法:

interface InterfaceWithPrivateMethods {
    
    private static String staticPrivate() {
        return "static private";
    }
    
    private String instancePrivate() {
        return "instance private";
    }
    
    default void check() {
        String result = staticPrivate();
        InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
            // anonymous class
        };
        result = pvt.instancePrivate();
    }
}}

JShell命令行工具

JShell是read–eval–print loop–REPL的缩写

简单地说,它是一个交互式工具,用于评估Java的声明、语句和表达式,以及API。测试小代码段非常方便,否则需要使用main方法创建一个新类。

jshell可执行文件本身可以在<JAVA_HOME>/bin文件夹中找到:

jdk-9\bin>jshell.exe
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"

交互式shell具有历史记录和自动完成功能;它还提供保存到文件和从文件加载所有或部分书面语句的功能:

jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!

代码片段在文件加载时执行。

JCMD子命令

让我们研究一下jcmd命令行实用程序中的一些新子命令。我们将得到JVM中加载的所有类及其继承结构的列表。

在下面的示例中,我们可以看到java.lang.Socket接口加载到运行Eclipse Neon的JVM中:

jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
|  implements java.io.Closeable/null (declared intf)
|  implements java.lang.AutoCloseable/null (inherited intf)
|  |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)
|  |--javax.net.ssl.SSLSocket/null
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)

jcmd命令的第一个参数是要在其上运行命令的JVM的进程id(PID)。

另一个有趣的子命令是set_vmflag。我们可以在线修改一些JVM参数,而无需重新启动JVM进程并修改其启动参数。

您可以使用子命令jcmd 14056找到所有可用的VM标志:VM.flags -all

多分辨率图像API

接口java.awt.image.MultiResolutionImage将一组具有不同分辨率的图像封装到单个对象中。我们可以根据给定的DPI度量和图像变换集检索特定分辨率的图像变体,或者检索图像中的所有变体。

这个java.awt.Graphics类从基于当前显示DPI度量和任何应用的变换的多分辨率图像中获取变量。

java.awt.image.BaseMultiResolutionImage提供基本实现:

BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
  = new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);

Variable Handles

API位于java.lang.invoke,由VarHandleMethodHandles组成。它提供了java.util.concurrent.atomicsun.misc.Unsafe对具有类似性能的对象字段和数组元素的操作。

java9模块化系统访问sun.misc.Unsafe从应用程序代码将不可能。

Publish-Subscribe 发布-订阅框架

java.util.concurrent.Flow提供支持反应流发布-订阅框架的接口。这些接口支持跨多个运行在jvm上的异步系统的互操作性。

我们可以使用实用类SubmissionPublisher来创建自定义组件。

统一JVM日志记录

这个特性为JVM的所有组件引入了一个通用的日志系统。它提供了进行日志记录的基础设施,但它没有添加来自所有JVM组件的实际日志记录调用。它也不向JDK中的Java代码添加日志记录。

日志框架定义了一组标记,例如gc、编译器、线程等。我们可以使用命令行参数-Xlog在启动期间打开日志记录。

让我们使用'debug'级别将带有'gc'标记的消息记录到名为'gc.txt文件“没有装饰:

java -Xlog:gc=debug:file=gc.txt:none ...

-Xlog:help 输出可能的选项和示例。可以在运行时使用jcmd命令修改日志配置。我们将把GC logs设置为info并将它们重定向到一个文件-gc_logs:

jcmd 9615 VM.log output=gc_logs what=gc

新的API

Immutable Set

java.util.Set.of()–创建给定元素的不可变集。在Java8中,创建一组多个元素需要几行代码。现在我们可以做的很简单:

Set<String> strKeySet = Set.of("key1", "key2", "key3");

此方法返回的集合是JVM内部类:java.util.ImmutableCollections.SetN,它扩展了公共java.util.AbstractSet. 它是不可变的——如果我们尝试添加或删除元素,就会抛出UnsupportedOperationException

也可以使用相同的方法将整个数组转换为一个集合。

Optional to Stream

java.util.Optional.stream()为您在可选元素上使用流的方式提供了一种简单的方法:

List<String> filteredList = listOfOptionals.stream()
  .flatMap(Optional::stream)
  .collect(Collectors.toList());
 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1403.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册