2 スニペット
JShellでは、Javaの文、変数、メソッド、クラス定義、インポートおよび式が使用可能です。Javaコードのこれらの要素は、スニペットとして参照されます。
スニペットの試用
JavaコードのスニペットはJShellに入力され、ただちに評価されます。結果に関するフィードバック、実行されたアクションおよび発生したエラーが表示されます。この項の例を使用して、JShellで試します。
詳細オプションを指定してJShellを起動し、使用可能な最大量のフィードバックを取得します。
% jshell -v
| Welcome to JShell -- Version 16.0.1
| For an introduction type: /help intro
プロンプトで次のサンプルの文を入力して、表示される出力を確認します。
jshell> int x = 45
x ==> 45
| created variable x : int
最初に結果が表示されます。これは、変数xの値は45という意味です。詳細モードで実行しているため、発生した内容の説明も表示されます。情報メッセージは、縦棒から始まります。作成された変数の名前と型の両方が示されていることに注意してください。
ノート:
末尾のセミコロンは入力しなくても、スニペットの補完時に自動的に追加されます。式が入力され、その中に名前付き変数がない場合、後で値を参照できるようにスクラッチ変数が作成されます。次の例は、式およびメソッドの結果のスクラッチの値を示しています。この例では、続行プロンプト(...>
)も示し、これはスニペットで複数行の入力を補完する必要がある場合に使用します。
jshell> 2 + 2
$3 ==> 4
| created scratch variable $3 : int
jshell> String twice(String s) {
...> return s + s;
...> }
| created method twice(String)
jshell> twice("Ocean")
$5 ==> "OceanOcean"
| created scratch variable $5 : String
定義の変更
コードを試すとき、変数の定義、メソッドまたはクラスが想定どおりに動作しない場合があります。定義は新しいものを入力すると、前の定義が上書きされ、容易に変更されます。
変数、メソッドまたはクラスの定義を変更するには、新しい定義を入力します。たとえば、「スニペットの試用」で定義したtwice
メソッドは、次の例では、新しい定義を取得します。
jshell> String twice(String s) {
...> return "Twice:" + s;
...> }
| modified method twice(String)
| update overwrote method twice(String)
jshell> twice("thing")
$7 ==> "Twice:thing"
| created scratch variable $7 : String
フィードバックでは、前述のcreated methodが表示されずに、modified methodと表示されることに注意してください。このメッセージは、定義が変更されたが、メッセージには同じシグネチャが含まれているので、既存のすべての使用方法が有効のままであることを意味しています。
互換性のない方法で、定義を変更することもできます。次の例は、x
文字列がint
からStringに変更されていることを示しています。
jshell> int x = 45
x ==> 45
| created variable x : int
jshell> String x
x ==> null
| replaced variable x : String
| update overwrote variable x : int
変数x
の型が変更され、フィードバックではreplacedと示されています。
フィードバックのレベルの変更
JShellは詳細フィードバック・モードで起動されると、多数のコメントが表示されます。/set feedback
コマンドを指定すると、出力の量と形式を設定できます(例: /set feedback concise
)。主に、他のウィンドウから貼り付けてJShellを使用する場合、プロンプトがなく、エラーのフィードバックのみを表示するフィードバック・モードの方がよい場合があります。この場合、/set feedback silent
コマンドを入力します。
前方参照
JShellでは、未定義のメソッド、変数またはクラスを参照するメソッド定義が使用可能です。この機能を実行するのは、試験的なプログラミングをサポートするため、および一部の形式のプログラミングで必要となるためです。
例として、球体のボリューム用のメソッドを定義する場合、次の式をメソッドvolume
として入力できます。
jshell> double volume(double radius) {
...> return 4.0 / 3.0 * PI * cube(radius);
...> }
| created method volume(double), however, it cannot be invoked until variable PI, and method cube(double) are declared
JShellでは定義が許可されますが、未定義の場合、警告が表示されます。定義を参照することはできますが、実行を試す際に、必要な要素がすべて定義されていなければ、失敗します。
jshell> double PI = 3.1415926535
PI ==> 3.1415926535
| created variable PI : double
jshell> volume(2)
| attempted to call method volume(double) which cannot be invoked until method cube(double) is declared
jshell> double cube(double x) { return x * x * x; }
| created method cube(double)
| update modified method volume(double)
jshell> volume(2)
$5 ==> 33.510321637333334
| created scratch variable $8 : double
すべて定義されると、volume
メソッドは動作します。
このメソッドを使用して、互換性のない代替方法を示します。たとえば、PI
の精度を変更するには、次の例のように新しい値を入力します。
jshell> BigDecimal PI = new BigDecimal("3.141592653589793238462643383")
PI ==> 3.141592653589793238462643383
| replaced variable PI : BigDecimal
| update modified method volume(double) which cannot be invoked until this error is corrected:
| bad operand types for binary operator '*'
| first type: double
| second type: java.math.BigDecimal
| return 4.0 / 3.0 * PI * cube(radius);
| ^------------^
| update overwrote variable PI : double
PI
の新しい定義は、volume()
の定義と型の互換性がありません。詳細モードで実行しているため、変更で影響を受ける他の定義の更新情報が表示されます。この場合、この情報は非互換性について説明するものです。詳細モードは、事前定義済のフィードバック・モードであり、更新情報が表示されます。他のフィードバック・モードでは、コードを実行しないかぎり、警告は表示されません。この目的は、更新のオーバーロードを回避することです。すべての事前定義モードで、volume()
メソッドを実行すると、問題が表示されます。
jshell> volume(2)
| attempted to call method volume(double) which cannot be invoked until this error is corrected:
| bad operand types for binary operator '*'
| first type: double
| second type: java.math.BigDecimal
| return 4.0 / 3.0 * PI * cube(radius);
| ^------------^
例外
例外のバックトレースでは、フィードバックにより、例外が発生したスニペットとスニペット内の場所が示されます。
JShellに入力したコード内の場所が#ID:line-number
として表示されます。ここで、スニペットIDは/list
コマンドで表示される番号で、line-numberはスニペット内の行番号です。次の例では、スニペット1 (divide()
メソッド)の2行目で例外が発生しています。
jshell> int divide(int x, int y) {
...> return x / y;
...> }
| created method divide(int,int)
jshell> divide(5, 0)
| java.lang.ArithmeticException thrown: / by zero
| at divide (#1:2)
| at (#2:1)
jshell> /list
1 : int divide(int x, int y) {
return x / y;
}
2 : divide(5, 0)
スニペットのタブ補完
スニペットを入力する場合、[Tab]キーを使用すると自動的に項目が補完されます。入力内容から項目を判定できない場合、使用可能なオプションが提示されます。
たとえば、「前方参照」のvolume
メソッドを入力する場合、メソッド名の先頭の数文字を入力して、[Tab]キーを押すと、入力を補完できます。
jshell> vol<Tab>
次のように入力されます。
jshell> volume(
項目の補完候補が複数ある場合、使用可能な候補が表示されます。
jshell> System.c<Tab>
class clearProperty( console() currentTimeMillis()
jshell> System.c
共通の文字が入力内容に追加され、さらに入力できるようにカーソルが入力の後に表示されます。
メソッド・コールの開きカッコの後に、[Tab]を押すと、パラメータ・タイプとともに補完候補が表示されます。
jshell> "hello".startsWith(<Tab>
Signatures:
boolean String.startsWith(String prefix, int toffset)
boolean String.startsWith(String prefix)
<press tab again to see documentation>
jshell> "hello".startsWith(
[Tab]を再度押すと、最初のメソッドのプレーン・テキスト・バージョンのドキュメントが表示されます。
jshell> "hello".startsWith(<Tab>
boolean String.startsWith(String prefix, int toffset)
Tests if the substring of this string beginning at the specified index starts with the
specified prefix.
Parameters:
prefix - the prefix.
toffset - where to begin looking in this string.
Returns:
true if the character sequence represented by the argument is a prefix of the substring of this
object starting at index toffset ; false otherwise. The result is false if toffset is
negative or greater than the length of this String object; otherwise the result is
the same as the result of the expression
this.substring(toffset).startsWith(prefix)
<press tab to see next documentation>
jshell> "hello".startsWith(
スニペットの変換
JShellは、最初にクラスが参照されるときに必要なクラスをインポートしたり、キーボード・ショートカットを使用して式を変数宣言に変換する際に便利です。
インポートされていない識別子を入力する場合、識別子の直後に[Shift]+[Tab]、[i]を押す(つまり、[Shift]を押したまま[Tab]を押し、放してから[i]を押す)と、オプションが表示され、インポートをセッションに追加できるようになります。
jshell> new JFrame<Shift+Tab i>
0: Do nothing
1: import: javax.swing.JFrame
Choice: 1
Imported: javax.swing.JFrame
jshell> new JFrame
必要なオプションの番号を入力します。複数のインポート・オプションを指定できます。
式を入力した後に[Shift]+[Tab]+[v]を押すと、式を変数宣言に変換できます。式が変数宣言の初期値になり、式の型が変数の型になります。[Shift]+[Tab]+[v]を押した後に、例で縦棒(|)によって示されるカーソルが、変数名を入力する必要のある行に表示されます。
jshell> new JFrame("Demo") <Shift+Tab v>
jshell> JFrame | = new JFrame("Demo")
ノート:
式は有効である必要があります。有効でなければ、変換リクエストは無視されます。例では、変数変換の前にJFrameのインポートが必要です。前述の例を完了するには、変数名frameをカーソル位置で入力して、[Enter]を押します。
jshell> JFrame frame = new JFrame("Demo")
frame ==> javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden, ... tPaneCheckingEnabled=true]
| created variable frame : JFrame
jshell>
式の結果タイプがインポートされない場合があります。この場合、次の例のように、[Shift]+[Tab]+[v]を押して、変数をインポートおよび作成します。
jshell> frame.getGraphics() <Shift+Tab v>
0: Do nothing
1: Create variable
2: import: java.awt.Graphics. Create variable
Choice: 2
Imported: java.awt.Graphics
jshell> Graphics | = frame.getGraphics()
前述の例を完了するには、変数名gcをカーソル位置で入力して、[Enter]を押します。
jshell> Graphics gc = frame.getGraphics()
| created variable gc :java.awt.Graphics
jshell>