Java9-クイックガイド

JAVA 9(別名jdk 1.9)は、JAVAプログラミング言語開発のメジャーリリースです。その初期バージョンは2017年9月21日にリリースされました。Java9リリースの主な目標は次のとおりです。

  • JDKおよびJavaStandard Editionプラットフォームを、小さなコンピューティングデバイスにうまく呼び出すことができるという意味でモジュール化すること。

  • JDKおよびJava実装の全体的なセキュリティを向上させるため。

  • JAVASEおよびEEプラットフォームでJavaコードライブラリと大規模アプリケーションのビルドプロセスとメンテナンスを簡単にするため。

  • プラットフォームとJDKの両方に簡単に適用できるJavaプラットフォームの標準モジュールシステムを設計および実装する。

新機能

Java 8には90以上の拡張機能が追加されており、最も重要な機能拡張は以下のとおりです。

  • Module −モジュールとして導入された新しい種類のJavaプログラミングコンポーネント。これは、名前付きの自己記述型のコードとデータのコレクションです。

  • REPL (JShell) − Javaプラットフォームに追加されたRead-Eval-PrintLoop(REPL)機能。

  • HTTP 2 Client −WebSocketとHTTP2ストリームおよびサーバープッシュ機能をサポートする新しいHTTPClientAPI。

  • Improved JavaDocs−HTML5出力の生成をサポートします。生成されたAPIドキュメントへの検索ボックスを提供します。

  • Multirelease JAR − JAR形式を拡張して、クラスファイルの複数のJavaリリース固有バージョンを単一のアーカイブに共存できるようにします。

  • Collection Factory Methods −これらのコレクションの不変インスタンスを作成するための、List、Set、およびMapインターフェイスの新しい静的ファクトリメソッド。

  • Private Interface Methods −プライベートおよびプライベート静的メソッドによる拡張インターフェース。

  • Process API Improvements −オペレーティングシステムプロセスを制御および管理するためのAPIの改善。

  • Stream API Improvements −オブジェクトシリアル化データの着信ストリームをフィルタリングできるようにすることで、セキュリティと堅牢性が強化されました。

  • Try With Resources improvement −最終変数をtry-with-resourcesステートメントのリソースとして使用できるようになりました。

  • Enhanced @Deprecated Annotation − @Deprecatedアノテーションが改良され、APIのステータスと意図された処理に関する詳細情報が提供されます。

  • Inner Class Diamond Operator −推論された型の引数型を指定できる場合は、ダイヤモンド演算子を匿名クラスで使用できるようにします。

  • Optional Class Improvements −新しい便利なメソッドがjava.util.Optionalクラスに追加されました。

  • Multiresolution Image API −異なる解像度の画像セットを単一の多重解像度画像にカプセル化することをサポートします。

  • CompletableFuture API improvements − CompletableFutureクラスの非同期メカニズムは、ProcessHandle.onExitメソッドを使用してプロセスが終了したときにアクションを実行できます。

  • Lightweight JSON − java9でjsonを介してドキュメントとデータストリームを消費および生成するために導入された軽量API。

  • Reactive Streams API − Java9のリアクティブプログラミングをサポートするためにJavaSE9の新しいリアクティブストリームAPIが導入されました。

ローカル環境のセットアップ

Javaプログラミング言語用に独自の環境をセットアップしたい場合は、このセクションでプロセス全体をガイドします。以下の手順に従って、Java環境をセットアップしてください。

Java SEは、無料でダウンロードできます。ダウンロードするには、ここをクリックして、オペレーティングシステムと互換性のあるバージョンをダウンロードしてください。

指示に従ってJavaをダウンロードし、 .exeマシンにJavaをインストールします。マシンにJavaをインストールしたら、正しいインストールディレクトリを指すように環境変数を設定する必要があります。

Windows 2000 / XPのパスの設定

Javaをc:\ Program Files \ java \ jdkディレクトリにインストールしたと仮定します-

  • 「マイコンピュータ」を右クリックし、「プロパティ」を選択します。

  • [詳細設定]タブの下にある[環境変数]ボタンをクリックします。

  • 次に、「Path」変数を編集し、その最後にJava実行可能ディレクトリへのパスを追加します。たとえば、パスが現在に設定されている場合はC:\Windows\System32、次のように編集します

C:\Windows\System32;c:\Program Files\java\jdk\bin

Windows 95/98 / MEのパスの設定

Javaをc:\ Program Files \ java \ jdkディレクトリにインストールしたと仮定します-

  • 'C:\ autoexec.bat'ファイルを編集し、最後に次の行を追加します-

SET PATH = %PATH%;C:\Program Files\java\jdk\bin

Linux、UNIX、Solaris、FreeBSDのパスの設定

環境変数PATHは、Javaバイナリがインストールされている場所を指すように設定する必要があります。これを行うのに問題がある場合は、シェルのドキュメントを参照してください。

たとえば、シェルとしてbashを使用する場合は、最後に次の行を追加します。 .bashrc

export PATH = /path/to/java:$PATH'

人気のあるJavaエディター

Javaプログラムを作成するには、テキストエディタが必要です。市場にはさらに洗練されたIDEがあります。最も人気のあるものを以下に簡単に説明します-

  • Notepad− Windowsマシンでは、メモ帳(このチュートリアルで推奨)やワードパッドなどの単純なテキストエディターを使用できます。Notepad ++は、機能を強化したフリーテキストエディタでもあります。

  • Netbeans −オープンソースで無料のJava IDEであり、からダウンロードできます。 https://www.netbeans.org/index.html。

  • Eclipse −これはEclipseオープンソースコミュニティによって開発されたJava IDEでもあり、からダウンロードできます。 https://www.eclipse.org/。

IDEまたは統合開発環境は、ソースコードエディタ、ビルドツール、デバッガなど、プログラミングを支援するためのすべての一般的なツールと機能を提供します。

Java 9、モジュールと呼ばれる新しい種類のプログラミングコンポーネントが導入されました。モジュールは、コードとデータの自己記述型のコレクションであり、それを識別するための名前が付いています。

特徴

Modulesコンポーネントにより、Java9で以下の機能拡張が追加されました。

  • 新しいオプションのフェーズであるリンク時間が導入されました。このフェーズは、コンパイル時と実行時の中間です。このフェーズでは、モジュールのセットを組み立てて最適化し、jlinkツールを使用してカスタムランタイムイメージを作成できます。

  • javac、jlink、およびjavaには、モジュールパスを指定するための追加オプションがあり、モジュールの定義をさらに見つけることができます。

  • JAR形式がモジュラーJARとして更新され、ルートディレクトリにmodule-info.classファイルが含まれています。

  • JMOD形式が導入されました。これは、ネイティブコードと構成ファイルを含めることができるパッケージ形式(JARと同様)です。

モジュールの作成

モジュールを作成する手順に従って、com.tutorialspoint.greetingsと言います。

ステップ1

フォルダC:\> JAVA \ srcを作成します。次に、作成しているモジュールの名前と同じフォルダーcom.tutorialspoint.greetingsを作成します。

ステップ2

次のコードを使用して、C:\> JAVA \ src \ com.tutorialspoint.greetingsフォルダーにmodule-info.javaを作成します。

module-info.java

module com.tutorialspoint.greetings { }

module-info.javaは、モジュールの作成に使用されるファイルです。このステップでは、com.tutorialspoint.greetingsという名前のモジュールを作成しました。慣例により、このファイルは、モジュール名と同じ名前のフォルダーに存在する必要があります。

ステップ3

モジュールにソースコードを追加します。次のコードを使用して、C:\> JAVA \ src \ com.tutorialspoint.greetings \ com \ tutorialspoint \ greetingsフォルダーにJava9Tester.javaを作成します。

Java9Tester.java

package com.tutorialspoint.greetings;

public class Java9Tester {
   public static void main(String[] args) {
      System.out.println("Hello World!");
   }
}

慣例により、モジュールのソースコードは、モジュールの名前である同じディレクトリにあります。

ステップ4

フォルダC:\> JAVA \ modsを作成します。次に、作成したモジュールの名前と同じフォルダーcom.tutorialspoint.greetingsを作成します。次に、モジュールをmodsディレクトリにコンパイルします。

C:/ > JAVA > javac -d mods/com.tutorialspoint.greetings 
   src/com.tutorialspoint.greetings/module-info.java 
   src/com.tutorialspoint.greetings/com/tutorialspoint/greetings/Java9Tester.java

ステップ5

モジュールを実行して結果を確認しましょう。次のコマンドを実行します。

C:/ > JAVA > java --module-path mods -m com.tutorialspoint.greetings/com.tutorialspoint.greetings.Java9Tester

ここで、module-pathはモジュールの場所をmodとして提供し、-mはメインモジュールを示します。

出力

次の出力がコンソールに出力されます。

Hello World!

REPLはRead-Eval-PrintLoopの略です。JShellを使用すると、JavaにはREPL機能があります。REPLを使用すると、javacを使用してコンパイルせずに、Javaベースのロジックをコーディングおよびテストし、計算結果を直接確認できます。

JShellの実行

コマンドプロンプトを開き、jshellと入力します。

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

JShellコマンドの表示

jshellコマンドの実行が開始されたら、/ helpと入力します。

jshell> /help
|  Type a Java language expression, statement, or declaration.
|  Or type one of the following commands:
|  /list [<name or id>|-all|-start]
|  list the source you have typed
|  /edit <name or id>
|  edit a source entry referenced by name or id
|  /drop <name or id>
|  delete a source entry referenced by name or id
|  /save [-all|-history|-start] <file>
|  Save snippet source to a file.
|  /open <file>
|  open a file as source input
|  /vars [<name or id>|-all|-start]
|  list the declared variables and their values
|  /methods [<name or id>|-all|-start]
|  list the declared methods and their signatures
|  /types [<name or id>|-all|-start]
|  list the declared types
|  /imports 
|  list the imported items

JShellコマンドの実行

jshellコマンドの実行が開始されたら、/ importsと入力し、使用されているインポートを確認します。

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
jshell>

JShellで計算を実行します。

JShellで簡単な計算を実行してみてください。

jshell> 3+1
$1 ==> 4 jshell> 13%7 $2 ==> 6
jshell> $2 $2 ==> 6
jshell>

JShellでの関数の作成と使用

intを取り、そのdouble値を返す関数doubled()を作成します。

jshell> int doubled(int i){ return i*2;}
|  created method doubled(int)
jshell> doubled(6)
$3 ==> 12
jshell>

JShellを終了します

/ exitと入力します。

jshell> /exit
| Goodbye

Javaドキュメントは、javadocツールを使用して生成できます。現在、html4.0形式のドキュメントを生成しています。Java 9では、コマンドライン引数で-html5オプションを使用して、html5形式でドキュメントを生成できます。

古いスタイルのJavaドキュメント

C:/ JAVAフォルダーにある次のコードについて考えてみます。

Tester.java

/**
 * @author MahKumar
 * @version 0.1
 */
public class Tester {
   /**
   * Default method to be run to print 
   * <p>Hello world</p>
   * @param args command line arguments
   */
   public static void main(String []args) {
      System.out.println("Hello World");
   }
}

次に、jdk 7のjavadocツールを実行して、ドキュメントを生成します。

C:\JAVA>javadoc -d C:/JAVA Tester.java
Loading source file tester.java...
Constructing Javadoc information...
Standard Doclet version 1.7.0_21
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

C:/ JAVAディレクトリにJavaドキュメントページが作成され、次の出力が表示されます。

検索とHTML5をサポートする新しいJavaドキュメント

-html5フラグを指定してjdk9のjavadocツールを実行し、新しいタイプのドキュメントを生成します。

C:\JAVA> javadoc -d C:/JAVA -html5 Tester.java
Loading source file Tester.java...
Constructing Javadoc information...
Standard Doclet version 9.0.1
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

D:/ testディレクトリに更新されたJavaドキュメントページが作成され、次の出力が表示されます。

Java 9では、jar形式が拡張され、プラットフォームごとに異なるバージョンのJavaクラスまたはリソースを維持および使用できる新機能が導入されました。JARでは、ファイルMANIFEST.MFファイルのメインセクションにMulti-Release:trueというエントリがあります。META-INFディレクトリには、そのサブディレクトリ(Java 9の場合は9から始まる)がバージョン固有のクラスとリソースファイルを格納するversionsサブディレクトリも含まれています。

この例では、マルチリリースjarを使用して2つのバージョンのTester.javaファイルを作成します。1つはjdk 7用、もう1つはjdk 9用で、異なるjdkバージョンで実行します。

ステップ

Step 1−フォルダc:/ test / java7 / com / tutorialspointを作成します。次の内容でTest.javaを作成します-

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 7");
   }
}

Step 2−フォルダc:/ test / java9 / com / tutorialspointを作成します。次の内容でTest.javaを作成します-

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 9");
   }
}

ソースコードをコンパイルします。

C:\test > javac --release 9 java9/com/tutorialspoint/Tester.java

C:\JAVA > javac --release 7 java7/com/tutorialspoint/Tester.java

マルチリリースjarを作成します

C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9.
Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java, 
   multiple resources with same name

JDK7で実行

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 7

JDK9で実行

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 9

Java 9では、不変のインスタンスを作成するために、新しいファクトリメソッドがList、Set、およびMapインターフェイスに追加されています。これらのファクトリメソッドは、コレクションをより冗長で簡潔な方法で作成するための便利なファクトリメソッドです。

コレクションを作成する古い方法

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = new HashSet<>();
      set.add("A");
      set.add("B");
      set.add("C");
      set = Collections.unmodifiableSet(set);
      System.out.println(set);
      List<String> list = new ArrayList<>();

      list.add("A");
      list.add("B");
      list.add("C");
      list = Collections.unmodifiableList(list);
      System.out.println(list);
      Map<String, String> map = new HashMap<>();

      map.put("A","Apple");
      map.put("B","Boy");
      map.put("C","Cat");
      map = Collections.unmodifiableMap(map);
      System.out.println(map);
   }
}

出力

次の出力が出力されます。

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}

新しい方法

java 9では、次のメソッドが、オーバーロードされた対応するメソッドとともに、List、Set、およびMapインターフェースに追加されます。

static <E> List<E> of(E e1, E e2, E e3);
static <E> Set<E>  of(E e1, E e2, E e3);
static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)

注意点

  • ListおよびSetインターフェースの場合、of(...)メソッドは、0から10のパラメーターを持ち、1つはvarargsパラメーターを持つようにオーバーロードされます。

  • Mapインターフェースの場合、of(...)メソッドは0から10のパラメーターを持つようにオーバーロードされます。

  • Mapインターフェースのパラメーターが10を超える場合は、var argsパラメーターを受け入れるofEntries(...)メソッドを使用できます。

コレクションを作成する新しい方法

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = Set.of("A", "B", "C");      
      System.out.println(set);
      List<String> list = List.of("A", "B", "C");
      System.out.println(list);
      Map<String, String> map = Map.of("A","Apple","B","Boy","C","Cat");
      System.out.println(map);
  
      Map<String, String> map1 = Map.ofEntries (
         new AbstractMap.SimpleEntry<>("A","Apple"),
         new AbstractMap.SimpleEntry<>("B","Boy"),
         new AbstractMap.SimpleEntry<>("C","Cat"));
      System.out.println(map1);
   }
}

出力

次の出力が出力されます。

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}
{A=Apple, B=Boy, C=Cat}

Java 8より前では、インターフェースは以下のタイプの変数/メソッドを持つことができました。

  • 定数変数
  • 抽象メソッド

したがって、インターフェースにメソッドを実装することはできません。より正確には、Java8より前のデフォルトの実装にすることはできません。例を参照してください。

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

final class LogMySql implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   void logInfo(String message);
   void logWarn(String message);
   void logError(String message);
   void logFatal(String message);

   void getConnection();
   void closeConnection();
}

出力

次の出力が表示されます。

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

上記の例では、各ログメソッドに独自の実装があります。Java 8では、インターフェイスは次のタイプの変数/メソッドを持つことができます。

  • 定数変数
  • 抽象メソッド
  • デフォルトのメソッド
  • 静的メソッド

Java 8を使用して、インターフェイス自体にデフォルトの実装と静的メソッドを設定しましょう。

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   default void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }
   
   default void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }
   
   default void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }
   
   default void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   static void getConnection() {
      System.out.println("Open Database connection");
   }
   static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

出力

次の出力が表示されます。

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

上記の例では、繰り返しがあります。Java 9では、インターフェースは次のタイプの変数/メソッドを持つことができます。

  • 定数変数
  • 抽象メソッド
  • デフォルトのメソッド
  • 静的メソッド
  • プライベートメソッド
  • プライベート静的メソッド

プライベートメソッドを用意して、Java9で使用してみましょう。

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   private void log(String message, String prefix) {
      getConnection();
      System.out.println("Log Message : " + prefix);
      closeConnection();
   }
   
   default void logInfo(String message) {
      log(message, "INFO");
   }
   
   default void logWarn(String message) {
      log(message, "WARN");
   }
   
   default void logError(String message) {
      log(message, "ERROR");
   }
   
   default void logFatal(String message) {
      log(message, "FATAL");
   }

   private static void getConnection() {
      System.out.println("Open Database connection");
   }
   
   private static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

出力

次の出力が表示されます。

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Java 9では、オペレーティングシステムプロセスの制御と管理を担当するProcessAPIが大幅に改善されました。ProcessHandleクラスは、プロセスのネイティブプロセスID、開始時間、累積CPU時間、引数、コマンド、ユーザー、親プロセス、および子孫を提供するようになりました。ProcessHandleクラスは、プロセスの活性をチェックし、プロセスを破棄するためのメソッドも提供します。onExitメソッドがあり、CompletableFutureクラスは、プロセスが終了したときに非同期でアクションを実行できます。

Tester.java

import java.time.ZoneId;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.io.IOException;

public class Tester {
   public static void main(String[] args) throws IOException {
      ProcessBuilder pb = new ProcessBuilder("notepad.exe");
      String np = "Not Present";
      Process p = pb.start();
      ProcessHandle.Info info = p.info();
      System.out.printf("Process ID : %s%n", p.pid());
      System.out.printf("Command name : %s%n", info.command().orElse(np));
      System.out.printf("Command line : %s%n", info.commandLine().orElse(np));

      System.out.printf("Start time: %s%n",
         info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
         .toLocalDateTime().toString()).orElse(np));

      System.out.printf("Arguments : %s%n",
         info.arguments().map(a -> Stream.of(a).collect(
            Collectors.joining(" "))).orElse(np));

      System.out.printf("User : %s%n", info.user().orElse(np));
   } 
}

出力

次の出力が表示されます。

Process ID : 5800
Command name : C:\Windows\System32\notepad.exe
Command line : Not Present
Start time: 2017-11-04T21:35:03.626
Arguments : Not Present
User: administrator

ストリームは、開発者が一連のオブジェクトから集計操作を実行できるようにJavaで導入されました。Java 9では、ストリームを改善するためにいくつかのメソッドが追加されています。

takeWhile(述語インターフェース)

構文

default Stream<T> takeWhile(Predicate<? super T> predicate)

takeWhileメソッドは、述語がfalseを返すまですべての値を取ります。順序付けられたストリームの場合、指定された述語に一致するこのストリームから取得された要素の最長のプレフィックスで構成されるストリームを返します。

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
         .forEach(System.out::print);		 
   } 
}

出力

takeWhileメソッドはすべてのa、b、およびc値を取り、文字列が空になると実行を停止します。

abc

dropWhile(述語インターフェース)

構文

default Stream<T> dropWhile(Predicate<? super T> predicate)

dropWhileメソッドは、述語がtrueを返すまで、開始時にすべての値を破棄します。順序付けられたストリームの場合、指定された述語に一致する要素の最長のプレフィックスを削除した後、このストリームの残りの要素で構成されるストリームを返します。

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
      System.out.println();
      Stream.of("a","b","c","","e","","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
   } 
}

出力

dropWhileメソッドはa、b、cの値を削除し、文字列が空になると、すべての値を取得します。

ef
ef

繰り返す

構文

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

iterateメソッドには、hasNext述語がfalseを返すとループを停止するパラメーターとしてhasNext述語が含まれるようになりました。

import java.util.stream.IntStream;

public class Tester {
   public static void main(String[] args) {
      IntStream.iterate(3, x -> x < 10, x -> x+ 3).forEach(System.out::println);
   } 
}

出力

3
6
9

ofNullable

構文

static <T> Stream<T> ofNullable(T t)

ofNullableメソッドは、NullPointerExceptionsを防止し、ストリームのnullチェックを回避するために導入されました。このメソッドは、nullでない場合は単一の要素を含むシーケンシャルストリームを返し、そうでない場合は空のストリームを返します。

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      long count = Stream.ofNullable(100).count();
      System.out.println(count);
  
      count = Stream.ofNullable(null).count();
      System.out.println(count);
   } 
}

出力

1
0

try-with-resourcesステートメントは、1つ以上のリソースが適切に宣言されたtryステートメントです。ここで、リソースは、不要になったときに閉じる必要があるオブジェクトです。try-with-resourcesステートメントは、要件の終了後に各リソースが閉じられるようにします。java.lang.AutoCloseableまたはjava.io.Closeableインターフェイスを実装する任意のオブジェクトをリソースとして使用できます。

Java 9より前では、以下の例に示すように、リソースはtryステートメントの前またはtryステートメント内で宣言されます。この例では、文字列を読み取るためのリソースとしてBufferedReaderを使用してから、BufferedReaderを閉じます。

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (BufferedReader br1 = br) {
         return br1.readLine();
      }
   }
}

出力

test

ここでは、tryステートメント内でリソースbr1を宣言してから、それを使用する必要があります。Java9では、br1を宣言する必要がなくなり、次のプログラムで同じ結果が得られます。

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (br) {
         return br.readLine();
      }
   }
}

出力

test

@DeprecatedアノテーションはJava5バージョンで導入されました。@Deprecatedアノテーションが付けられたプログラム要素は、次のいずれかの理由で使用しないことを意味します-

  • その使用法はエラーにつながる可能性があります。
  • 将来のバージョンでは互換性がなくなる可能性があります。
  • 将来のバージョンで削除される可能性があります。
  • より優れた効率的な代替手段がそれに取って代わりました。

非推奨の要素が使用されるたびに、コンパイラは警告を生成します。Java 9では、@ Deprecatedアノテーションに2つの新しい機能拡張が行われました。

  • forRemoval−注釈付き要素が将来のバージョンで削除される可能性があるかどうかを示します。デフォルト値はfalseです。

  • since−注釈付き要素が非推奨になったバージョンを返します。デフォルト値は空の文字列です。

以来非推奨

Java 9でのブールクラスjavadocの次の例は、@ Deprecatedアノテーションでのsince属性の使用を示しています。

ブールクラス

forRemovalで非推奨

次のJava9のシステムクラスjavadocの例は、@ DeprecatedアノテーションでのforRemoval属性の使用を示しています。

システムクラス

ダイヤモンド演算子は、コードを読みやすくするためにJava 7で導入されましたが、匿名内部クラスでは使用できませんでした。Java 9では、匿名クラスとともに使用して、コードを簡素化し、読みやすさを向上させることができます。Java9より前の次のコードを検討してください。

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<Integer>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<Object>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

出力

1
2
Test

Java 9では、以下に示すように、匿名クラスで<>演算子を使用できます。

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

出力

1
2
Test

オプションのクラスは、nullチェックとNullPointerExceptionの問題を回避するためにJava8で導入されました。Java 9では、機能を向上させるために3つの新しいメソッドが追加されています。

  • stream()
  • ifPresentOrElse()
  • or()

stream()メソッド

構文

public Stream<T> stream()

値が存在する場合は、その値のみを含むシーケンシャルストリームを返します。それ以外の場合は、空のストリームを返します。

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Tester {
public static void main(String[] args) {
   List<Optional<String>> list = Arrays.asList (
      Optional.empty(), 
      Optional.of("A"), 
      Optional.empty(), 
      Optional.of("B"));

   //filter the list based to print non-empty values
  
   //if optional is non-empty, get the value in stream, otherwise return empty
   List<String> filteredList = list.stream()
      .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
      .collect(Collectors.toList());

   //Optional::stream method will return a stream of either one 
   //or zero element if data is present or not.
   List<String> filteredListJava9 = list.stream()
      .flatMap(Optional::stream)
      .collect(Collectors.toList());

      System.out.println(filteredList);
      System.out.println(filteredListJava9);
   }  
}

出力

[A, B]
[A, B]

ifPresentOrElse()メソッド

構文

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

値が存在する場合は、その値を使用して指定されたアクションを実行します。それ以外の場合は、指定された空ベースのアクションを実行します。

import java.util.Optional;

public class Tester {
   public static void main(String[] args) {
      Optional<Integer> optional = Optional.of(1);

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));

      optional = Optional.empty();

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));
   }  
}

出力

Value: 1
Not Present.

or()メソッド

構文

public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

値が存在する場合は、値を説明するオプションを返します。それ以外の場合は、指定する関数によって生成されたオプションを返します。

import java.util.Optional;
import java.util.function.Supplier;

public class Tester {
   public static void main(String[] args) {
      Optional<String> optional1 = Optional.of("Mahesh");

      Supplier<Optional<String>> supplierString = () -> Optional.of("Not Present");

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));
    
      optional1 = Optional.empty();    

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));  
   }  
}

出力

Value: Mahesh
Value: Not Present

Java 9では、異なる解像度のバリエーションを持つ複数の画像をサポートする新しいマルチ解像度画像APIが導入されました。このAPIを使用すると、解像度の異なる画像のセットを単一のマルチ解像度画像として使用できます。多重解像度画像の主な操作は次のとおりです。

  • Image getResolutionVariant(double destImageWidth, double destImageHeight) −指定されたサイズでこの論理画像を表すのに最適なバリアントである特定の画像を取得します。

  • List<Image> getResolutionVariants() −すべての解像度バリアントの読み取り可能なリストを取得します。

import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.awt.Image;
import java.awt.image.MultiResolutionImage;
import java.awt.image.BaseMultiResolutionImage;

import javax.imageio.ImageIO;

public class Tester {
   public static void main(String[] args) throws IOException, MalformedURLException {

      List<String> imgUrls = List.of("http://www.tutorialspoint.com/java9/images/logo.png",
         "http://www.tutorialspoint.com/java9/images/mini_logo.png",
         "http://www.tutorialspoint.com/java9/images/large_logo.png");

      List<Image> images = new ArrayList<Image>();

      for (String url : imgUrls) {
         images.add(ImageIO.read(new URL(url)));
      }

      // read all images into one multiresolution image
      MultiResolutionImage multiResolutionImage = 
         new BaseMultiResolutionImage(images.toArray(new Image[0]));

      // get all variants of images
      List<Image> variants = multiResolutionImage.getResolutionVariants();

      System.out.println("Total number of images: " + variants.size());

      for (Image img : variants) {
         System.out.println(img);
      }

      // get a resolution-specific image variant for each indicated size
      Image variant1 = multiResolutionImage.getResolutionVariant(156, 45);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 
         156, 45, variant1.getWidth(null), variant1.getHeight(null));

      Image variant2 = multiResolutionImage.getResolutionVariant(311, 89);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 311, 89, 
         variant2.getWidth(null), variant2.getHeight(null));

      Image variant3 = multiResolutionImage.getResolutionVariant(622, 178);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 622, 178, 
         variant3.getWidth(null), variant3.getHeight(null));

      Image variant4 = multiResolutionImage.getResolutionVariant(300, 300);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 300, 300, 
         variant4.getWidth(null), variant4.getHeight(null));
   }  
}

出力

Total number of images: 3
BufferedImage@7ce6a65d: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =311 
height = 89 #numDataElements 4 dataOff[0] = 3

BufferedImage@4c762604: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =156 
height = 45 #numDataElements 4 dataOff[0] = 3

BufferedImage@2641e737: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =622 
height = 178 #numDataElements 4 dataOff[0] = 3

Image for destination[156,45]: [311,89]
Image for destination[311,89]: [311,89]
Image for destination[622,178]: [622,178]
Image for destination[300,300]: [622,178]

CompletableFutureクラスはJava8で導入され、値とステータスを明示的に設定することで完了できるFutureを表します。java.util.concurrent.CompletionStageとして使用できます。これは、将来の完了時にトリガーされた依存関数とアクションをサポートします。Java 9では、CompletableFutureAPIがさらに拡張されました。以下は、APIに加えられた関連する変更です。

  • 遅延とタイムアウトのサポート。
  • サブクラス化のサポートが改善されました。
  • 新しいファクトリメソッドが追加されました。

遅延とタイムアウトのサポート

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

このメソッドは、指定されたタイムアウトの前に完了しなかった場合、指定された値でこのCompletableFutureを完了します。

public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

このメソッドは、指定されたタイムアウトの前に完了しない場合、このCompletableFutureをTimeoutExceptionで例外的に完了します。

サブクラス化のサポートの改善

public Executor defaultExecutor()

エグゼキュータを指定しない非同期メソッドに使用されるデフォルトのエグゼキュータを返します。このメソッドはサブクラスでオーバーライドされ、エグゼキュータを返し、少なくとも1つの独立したスレッドを提供することができます。

public <U> CompletableFuture<U> newIncompleteFuture()

CompletionStageメソッドによって返されるタイプの新しい不完全なCompletableFutureを返します。CompletableFutureクラスのサブクラスは、このCompletableFutureと同じクラスのインスタンスを返すために、このメソッドをオーバーライドする必要があります。デフォルトの実装は、CompletableFutureクラスのインスタンスを返します。

新しいファクトリメソッド

public static <U> CompletableFuture<U> completedFuture(U value)

このファクトリメソッドは、指定された値ですでに完了している新しいCompletableFutureを返します。

public static <U> CompletionStage<U> completedStage(U value)

このファクトリメソッドは、指定された値ですでに完了している新しいCompletionStageを返し、インターフェイスCompletionStageに存在するメソッドのみをサポートします。

public static <U> CompletionStage<U> failedStage(Throwable ex)

このファクトリメソッドは、指定された例外を除いてすでに例外的に完了し、インターフェイスCompletionStageに存在するメソッドのみをサポートする新しいCompletionStageを返します。

上記の機能とは別に、Java 9では、JDKプラットフォームに対してさらに多くの機能拡張が行われます。それらのいくつかを以下に示します。

  • GC(ガベージコレクター)の改善
  • スタックウォーキングAPI
  • 着信シリアル化データのフィルタリング
  • AppletAPIの廃止
  • 文字列の連結を示す
  • 強化されたメソッドハンドル
  • JavaプラットフォームロギングAPIとサービス
  • コンパクトストリング
  • NashornのパーサーAPI