モジュール jdk.jshell

パッケージjdk.jshell


パッケージjdk.jshell
Javaプログラミング言語コードの"snippets"を対話的に評価するRead-Eval-Print Loop (REPL)などのツールを作成するためのインタフェースを提供します。 ここで、"snippet"は単一の式、文または宣言です。 この機能は、IDEなどのツールを拡張するために使用することも、スタンドアロンにすることもできます。

JShellは中央クラスです。 JShellのインスタンスは、評価状態を保持します。これは、ソース・スニペットの現在のセットと生成した実行状態の両方です。

各ソース・スニペットは、Snippetのサブクラスのインスタンスで表されます。 たとえば、文はStatementSnippetのインスタンスで表され、メソッド宣言はMethodSnippetのインスタンスで表されます。 スニペットは、コードのスニペットが1つ以上含まれる入力を使用してJShell.eval(String)が呼び出されたときに作成されます。

スニペットのコンパイル・ステータスの変更は、SnippetEventで報告されます。 スニペットのステータスには3つの主要な変更があります: evalを使用して作成でき、JShell.drop(jdk.jshell.Snippet)を使用してアクティブなソース状態からドロップでき、別のスニペットのステータス変更の結果としてそのステータスを更新できます。 例えば: 与えられたjsJShellのインスタンス、js.eval("int x = 5;")を実行すると、変数xがソース状態に追加され、xVarSnippetの作成を記述するイベントが生成されます。 その後、js.eval("int timesx(int val) { return val * x; }")を実行すると、ソース状態にメソッドが追加され、timesxMethodSnippetの作成を記述するイベントが生成されます。 varxevalへの最初の呼び出しによって作成されたスニペットを保持し、js.drop(varx)を実行すると2つのイベントが生成されるものとします: 1つは変数スニペットのステータスをDROPPEDに変更するメソッド、もう1つはメソッド・スニペット(これで、xへの未解決の参照があります)を更新するメソッドです。

もちろん、APIの一般的なアプリケーションの場合、入力は固定文字列ではなく、ユーザーから取得されます。 以下は、APIを使用してREPLを実装する方法の非常に簡略化された例です。

 
     import java.io.ByteArrayInputStream;
     import java.io.Console;
     import java.util.List;
     import jdk.jshell.*;
     import jdk.jshell.Snippet.Status;

     class ExampleJShell {
         public static void main(String[] args) {
             Console console = System.console();
             try (JShell js = JShell.create()) {
                 do {
                     System.out.print("Enter some Java code: ");
                     String input = console.readLine();
                     if (input == null) {
                         break;
                     }
                     List<SnippetEvent> events = js.eval(input);
                     for (SnippetEvent e : events) {
                         StringBuilder sb = new StringBuilder();
                         if (e.causeSnippet() == null) {
                             //  We have a snippet creation event
                             switch (e.status()) {
                                 case VALID:
                                     sb.append("Successful ");
                                     break;
                                 case RECOVERABLE_DEFINED:
                                     sb.append("With unresolved references ");
                                     break;
                                 case RECOVERABLE_NOT_DEFINED:
                                     sb.append("Possibly reparable, failed  ");
                                     break;
                                 case REJECTED:
                                     sb.append("Failed ");
                                     break;
                             }
                             if (e.previousStatus() == Status.NONEXISTENT) {
                                 sb.append("addition");
                             } else {
                                 sb.append("modification");
                             }
                             sb.append(" of ");
                             sb.append(e.snippet().source());
                             System.out.println(sb);
                             if (e.value() != null) {
                                 System.out.printf("Value is: %s\n", e.value());
                             }
                             System.out.flush();
                         }
                     }
                 } while (true);
             }
             System.out.println("\nGoodbye");
         }
     }
 
 

ステータス変更イベントに登録するには、JShell.onSnippetEvent(java.util.function.Consumer)を使用します。 これらのイベントは、evalおよびdropによってのみ生成され、これらのメソッドの戻り値は、そのコールによって生成されるイベントのリストです。 したがって、前述の例のように、イベントを受信するために登録せずにイベントを使用できます。

この例を試すと、セミコロンを使用した文または変数宣言の終了に失敗すると、単に失敗することになります。 未完了のエントリ(例えば、所望のマルチ・ライン法)も、1行の後に失敗します。 SourceCodeAnalysisのユーティリティは、ソース境界および完全性分析を提供し、このようなケースに対処します。 SourceCodeAnalysisは、タブ補完で使用される可能性がある入力の推奨完了も提供します。

導入されたバージョン:
9