更新時間:2022-10-14 09:58:02 來源:動力節點 瀏覽1284次
Java 9 帶有豐富的特性集。雖然沒有新的語言概念,但新的 API 和診斷命令肯定會引起開發人員的興趣。
在這篇文章中,我們將對一些新功能進行快速、高級的了解;此處提供了新功能的完整列表。
讓我們從最重要的開始——將模塊化引入 Java 平臺。
模塊化系統提供類似于 OSGi 框架系統的功能。模塊具有依賴關系的概念,可以導出公共 API 并將實現細節隱藏/私有。
這里的主要動機之一是提供模塊化 JVM,它可以在可用內存少得多的設備上運行。JVM 只能使用應用程序所需的那些模塊和 API 運行。查看此鏈接以了解這些模塊是什么。
此外,無法再從應用程序代碼訪問com.sun.*等 JVM 內部(實現)API 。
簡而言之,這些模塊將在位于 java 代碼層次結構頂部的名為module-info.java的文件中進行描述:
module com.baeldung.java9.modules.car {
requires com.baeldung.java9.modules.engines;
exports com.baeldung.java9.modules.car.handling;
}
我們的模塊車需要模塊引擎來運行并導出一個包進行處理。
期待已久的舊HttpURLConnection替代品。
新 API 位于java.net.http包下。
它應該支持HTTP/2 協議和WebSocket握手,其性能應該可以與Apache HttpClient、Netty和Jetty相媲美。
讓我們通過創建和發送一個簡單的 HTTP 請求來看看這個新功能。
更新:HTTP 客戶端 JEP正在移至 Incubator 模塊,因此它不再在包java.net.http中可用,而是在jdk.incubator.http 下可用。
快速獲取請求
API 使用 Builder 模式,這使得快速使用變得非常容易:
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
進程 API 已針對控制和管理操作系統進程進行了改進。
(1)處理信息
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子類提供有關該過程的詳細信息。
(2)銷毀進程
現在 - 讓我們使用destroy()停止所有正在運行的子進程:
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});
(1)試用資源
在 Java 7 中,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) { }
(2)鉆石運算符擴展
現在我們可以將菱形運算符與匿名內部類結合使用:
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
};
(3)接口私有方法
即將發布的 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 是 read-eval-print 循環——簡稱 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"
交互式外殼帶有歷史記錄和自動完成功能;它還提供諸如保存和加載文件、所有或部分書面語句的功能:
jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!
代碼片段在文件加載時執行。
讓我們探索jcmd命令行實用程序中的一些新子命令。我們將獲得 JVM 中加載的所有類及其繼承結構的列表。
在下面的示例中,我們可以看到運行 Eclipse Neon 的 JVM 中加載的java.lang.Socket的層次結構:
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.flags -all找出所有可用的 VM 標志
接口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]);
API 位于java.lang.invoke下,由VarHandle和MethodHandles組成。它在對象字段和數組元素上提供等效的java.util.concurrent.atomic和sun.misc.Unsafe操作,具有相似的性能。
使用 Java 9 Modular 系統將無法從應用程序代碼訪問sun.misc.Unsafe 。
java.util.concurrent.Flow類提供了支持Reactive Streams發布-訂閱框架的接口。這些接口支持跨在 JVM 上運行的多個異步系統的互操作性。
我們可以使用實用程序類SubmissionPublisher來創建自定義組件。
此功能為 JVM 的所有組件引入了一個通用的日志記錄系統。它提供了進行日志記錄的基礎設施,但它沒有添加來自所有 JVM 組件的實際日志記錄調用。它也不向 JDK 中的 Java 代碼添加日志記錄。
日志框架定義了一組標簽——例如gc、編譯器、線程等。我們可以使用命令行參數-Xlog在啟動期間打開日志。
讓我們使用'debug'級別將帶有'gc'標簽的消息記錄到一個名為'gc.txt'的文件中,沒有任何修飾:
java -Xlog:gc=debug:file=gc.txt:none ...
-Xlog:help將輸出可能的選項和示例。可以使用jcmd命令在運行時修改日志記錄配置。我們將設置 GC 日志為 info 并將它們重定向到一個文件 - gc_logs:
jcmd 9615 VM.log output=gc_logs what=gc
(1)不可變集
java.util.Set.of() – 創建給定元素的不可變集合。在 Java 8 中,創建一個由多個元素組成的 Set 需要幾行代碼。現在我們可以簡單地做到這一點:
Set<String> strKeySet = Set.of("key1", "key2", "key3");
(2)可選擇流式傳輸
java.util.Optional.stream()為我們提供了一種在 Optional 元素上使用 Streams 功能的簡單方法:
List<String> filteredList = listOfOptionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習