先月からProject Kullaで提供しているJShellを紹介しています。JShellはJavaのREPLツールで、インタラクティブにJavaのコードを実行できるツールです。JShellで実行するには、クラスとmainメソッドを作成する必要はありません。変数定義やメソッド定義を、いきなり記述できます。このようなコードをコードの断片という意味からスニペットと呼びます。
前回は、そのスニペットの制限について紹介しました。例えば、パッケージが使えないなどがスニペットの制限となります。また、JShellの起動オプションについても紹介しました。
今回は、JShellに組み込まれているコマンドについて紹介します。コマンドは/で始まる文字列で構成されます。例えば、ヘルプを表示するコマンドは/helpになります。コマンドはいくつかのグループに分けられます。以下、グループごとにコマンドを紹介していきます。
スニペットの参照
まずは、スニペットを参照するためのコマンドです。JShellでは行単位でスニペットを実行していきますが、どのようなスニペットを実行したか後から参照したいことがよくあります。参照する対象によって、複数のコマンドが提供されています。
リスト表示
スニペットをリストとして表示するコマンドが/listコマンドです。例えば、以下に示すスニペットを実行した後に、/listコマンドを実行してみます。
jshell> String hello = "Hello, Java!";
hello ==> "Hello, Java!"
jshell> hello.chars().
...> map(p -> Character.toUpperCase((char)p)).
...> forEach(p -> System.out.printf("%c", p));
HELLO, JAVA!
jshell> /list
1 : String hello = "Hello, Java!";
2 : hello.chars().
map(p -> Character.toUpperCase((char)p)).
forEach(p -> System.out.printf("%c", p));
jshell>
/listコマンドを実行すると、番号付きでスニペットが表示されます。この番号はスニペットIDと呼ばれます。/listコマンドの引数として、スニペットIDもしくは変数名、メソッド名、型名を指定することもできます。
jshell> /list 2
2 : hello.chars().
map(p -> Character.toUpperCase((char)p)).
forEach(p -> System.out.printf("%c", p));
jshell> /list hello
1 : String hello = "Hello, Java!";
jshell>
上の例ではスニペットIDの2を指定してhello.chars()で始まる行を表示しています。その後に、変数helloを指定して、変数helloの宣言を表示しています。筆者はスニペットIDを指定することはほとんどありませんが、名前で表示させることはよく使います。
JShellでは、式の値を変数に代入していない場合、$で始まる一時変数に格納されます。この一時変数名でリストを表示することも可能です。
jshell> 1+2
$1 ==> 3
jshell> /list $1
1 : 1+2
jshell>
なお、/listコマンドはデフォルトではエラーを起こしたスニペットは表示しません。例えば、次に示すスニペットを入力したとします。
jshell> int a = "A"
| エラー:
| 不適合な型: java.lang.Stringをintに変換できません:
| int a = "A";
| ^-^
jshell> /list
1 : String hello = "Hello, Java!";
2 : hello.chars().
map(p -> Character.toUpperCase((char)p)).
forEach(p -> System.out.printf("%c", p));
jshell>
これに対し、-allオプションを使用すると、エラーの発生したスニペットも表示します。また、スタートアップスニペットで実行したスニペットも一緒に表示します。
jshell> /list -all
s1 : import java.io.*;
s2 : import java.math.*;
s3 : import java.net.*;
s4 : import java.nio.file.*;
s5 : import java.util.*;
s6 : import java.util.concurrent.*;
s7 : import java.util.function.*;
s8 : import java.util.prefs.*;
s9 : import java.util.regex.*;
s10 : import java.util.stream.*;
1 : String hello = "Hello, Java!";
2 : hello.chars().
map(p -> Character.toUpperCase((char)p)).
forEach(p -> System.out.printf("%c", p));
e1 : int a = "A"
jshell>
sで始まるスニペットIDがスタートアップスニペットで実行されたスニペット、eで始まるスニペットIDがエラーが発生したスニペットになります。