Java 9の新機能
1概要
Java 9には豊富な機能セットが付属しています。新しい言語の概念はありませんが、新しいAPIと診断コマンドは開発者にとって間違いなくおもしろいでしょう。
今回の記事では、いくつかの新機能について簡単に概要を説明します。新機能の完全なリストはhttp://openjdk.java.net/projects/jdk9/[ここ]にあります。
** 2モジュラーシステム – ジグソープロジェクト
大きなものから始めましょう – Javaプラットフォームにモジュール性をもたらします。
モジュラーシステムは、OSGiフレームワークのシステムと同様の機能を提供します。モジュールは依存関係の概念を持ち、パブリックAPIをエクスポートし、実装の詳細を非表示/非公開にすることができます。
ここでの主な動機の1つは、利用可能なメモリがはるかに少ないデバイスで実行できるモジュール式JVMを提供することです。 JVMは、アプリケーションに必要なモジュールとAPIだけで実行できます。これらのモジュールが何であるかの説明についてはhttp://cr.openjdk.java.net/~mr/jigsaw/ea/module-summary.html[このリンク]をチェックしてください。
また、
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;
}
私たちのモジュール
car
はモジュール
engine
が
handling
用のパッケージを実行してエクスポートすることを要求します。
より詳しい例については、OpenJDK
http://openjdk.java.net/projects/jigsaw/quick-start
[Project Jigsaw:
モジュールシステムクイックスタートガイド]。
3新しいHTTPクライアント
待望の古い
HttpURLConnection
の置き換え。
-
新しいAPIは
java.net.http
パッケージの下にあります。
これはhttps://http2.github.io/[HTTP/2 protocol]とhttps://en.wikipedia.org/wiki/WebSocket[WebSocket]の両方のハンドシェイクをサポートするはずです。/hc.apache.org/httpcomponents-client-ga/[Apache HttpClient]、http://netty.io[Netty]、およびhttp://eclipse.org/jetty[Jetty]。
単純なHTTPリクエストを作成して送信することによって、この新しい機能を見てみましょう。
-
更新:http://openjdk.java.net/jeps/110[HTTP Client JEP]はIncubatorモジュールに移動されているので、
java.net.http
パッケージには含まれておらず、代わりに
jdkの下で利用可能です。 incubator.http .
**
3.1. クイックGETリクエスト
この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());
4プロセスAPI
オペレーティングシステムプロセスを制御および管理するためのプロセスAPIが改善されました。
4.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
サブクラスはプロセスに関する詳細を提供します。
4.2. 破壊プロセス
それでは、
destroy()
を使って、実行中のすべての子プロセスを停止しましょう。
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});
5小さな言語の修正
5.1. リソースを使ってみる
Java 7では、
try-with-resources
構文では、ステートメントによって管理されている各リソースに対して新しい変数を宣言する必要があります。
Java 9では、さらに洗練された機能があります。リソースが最終または実質的に最終の変数によって参照される場合、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) { }
5.2. ダイヤモンドオペレーターエクステンション
これで、匿名内部クラスと組み合わせて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
};
5.3. インターフェースプライベートメソッド
今後のJVMバージョンのインタフェースには
private
メソッドを含めることができます。これを使用して、長いデフォルトメソッドを分割できます。
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();
}
}}
6. JShellコマンドラインツール
JShellはread-eval-printループです – 略してREPLです。
簡単に言えば、それはAPIと共にJavaの宣言、ステートメント、および式を評価するための対話型ツールです。
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!
コードスニペットはファイルのロード時に実行されます。
7. JCMDサブコマンド
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
commandの最初のパラメーターは、コマンドを実行したいJVMのプロセスID(PID)です。
もう1つの興味深いサブコマンドは
set
vmflag__です。 JVMプロセスを再起動して起動パラメータを変更することなく、JVMパラメータをオンラインで変更できます。
サブコマンド
jcmd 14056 VM.flags -all
を使用して、使用可能なすべてのVMフラグを見つけることができます。
8高解像度画像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]);
9可変ハンドル
APIは
java.lang.invoke
の下にあり、
VarHandle
と
MethodHandles
で構成されています。オブジェクトフィールドおよび配列要素に対して、
java.util.concurrent.atomic
および
sun.misc.Unsafe
操作と同等のパフォーマンスを提供します。
-
Java 9 Modularシステムでは、
sun.misc.Unsafe
へのアプリケーションコードからのアクセスはできません。
10発行 – 購読フレームワーク
クラス
java.util.concurrent.Flow
は、http://www.reactive-streams.org/[Reactive Streams]publish-subscribeフレームワークをサポートするインタフェースを提供します。これらのインタフェースは、JVM上で実行されている多数の非同期システムにわたる相互運用性をサポートしています。
カスタムコンポーネントを作成するには、ユーティリティクラス
SubmissionPublisher
を使用できます。
11統合JVMロギング
この機能は、JVMのすべてのコンポーネントに共通のロギングシステムを導入します。ロギングを実行するためのインフラストラクチャを提供しますが、すべてのJVMコンポーネントからの実際のロギング呼び出しを追加するわけではありません。 JDKのJavaコードへのロギングも追加されません。
ロギングフレームワークは、
gc
、
compiler
、
threads
など、
tags
のセットを定義します。起動時にロギングを有効にするには、コマンドラインパラメータ
-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
12. 新しいAPI
12.1. 不変セット
java.util.Set.of()
– 与えられた要素の不変な集合を作成します。 Java 8では、複数の要素のセットを作成するには、複数行のコードが必要です。これで、次のように簡単に実行できます。
Set<String> strKeySet = Set.of("key1", "key2", "key3");
このメソッドによって返される
Set
はJVMの内部クラスです。
public
java.util.AbstractSet
を拡張する
java.util.ImmutableCollections.SetN
。不変です – 要素を追加または削除しようとすると、
UnsupportedOperationException
がスローされます。
同じ方法で配列全体を
Set
に変換することもできます。
12.2. ストリーミングのオプション
java.util.Optional.stream()
を使用すると、オプション要素でStreamsの機能を簡単に使用できます。
List<String> filteredList = listOfOptionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());