LoginSignup
1
0

jshell使ってみた

Last updated at Posted at 2023-08-12

jshellをつかってみました。
サイトに載っているサンプル実行するなどでは十分使えました。わざわざIDEでプロジェクト作ってー、main作ってーってやらなくていいので楽でした。
ただクラスを何個か新規で定義するほどの規模になったら、ちゃんと開発環境構築して、デバックできるほうがいいのかな、と思いました。

Java Shellユーザー・ガイド より

■ JShellの概要
Java Shellツール(JShell)は、Javaプログラミング言語を学習したり、およびJavaコードのプロトタイプを作成するための対話型ツールです。JShellはRead-Evaluate-Print Loop (REPL)であり、入力時に宣言、文および式を評価し、ただちに結果を表示します。ツールは、コマンドラインから実行されます。

■JShellを使用する理由
JShellを使用すると、一度に1つずつプログラム要素を入力したり、ただちに結果を確認したり、必要に応じて調整できます。
Javaプログラムの開発には、通常、次のプロセスが含まれます。
・完全なプログラムを作成します。
・これをコンパイルして、エラーを修正します。
・プログラムを実行します。
・問題がある場所を調べます。
・これを編集します。
のプロセスを繰り返します。
JShellを使用すると、プログラム開発時にコードを試したり、オプションを容易に調べることができます。JShellセッションで、個々の文をテストしたり、様々なバリエーションのメソッドを試したり、よく知らないAPIを試すことができます。JShellはIDEに取ってかわるものではありません。プログラムの開発時に、コードをJShellに貼り付けてこれを試してから、動作するコードをJShellからプログラム・エディタまたはIDEに貼り付けます。

環境構築

java JDKのインストール

さすがにJDKはインストールしないとだめです。

ダウンロード

ここから、とりえず現時点で最新の20をダウンロードして、インストール。

使ってみよう

起動・停止

起動

コマンドプロンプトかpownershellで「jshell」と入力。

jshell

起動するとこんな感じ。

C:\xxxxx>jshell
|  JShellへようこそ -- バージョン18
|  概要については、次を入力してください: /help intro

jshell>

停止

「/exit」と入力。

jshell> /exit
|  終了します

四則演算

jshell> 10 + 10
$1 ==> 20
jshell> (10 + 10) * 100
$2 ==> 2000

数値型について

jshell> 22 / 7
$4 ==> 3

基本、整数っぽい。
浮動小数点型にしたい時は、どちらかを浮動小数点型にする。

jshell> 22 / 7.0
$5 ==> 3.142857142857143

文字列演算

jshell> "ABC" + "DEF"
$3 ==> "ABCDEF"

比較演算

 jshell> 1 == 1
$6 ==> true
jshell> 1 == 2 || 3 == 3
$1 ==> true
jshell> 1 == 2 || 3 == 3 && (4 == 5)
$2 ==> false

※文字列はString クラスの equals メソッドを使用ですよ。

メソッド

メソッド一覧

メソッド名のスペルわすれた!の時のために。

あとえば、文字列のメソッド一覧を表示したい時は
「"文字列".」と入力して、[TAB]キー。
※ドットの入力わすれないように。

jshell> "test".
charAt(                chars()                codePointAt(           codePointBefore(       codePointCount(
codePoints()           compareTo(             compareToIgnoreCase(   concat(                contains(
contentEquals(         describeConstable()    endsWith(              equals(                equalsIgnoreCase(
formatted(             getBytes(              getChars(              getClass()             hashCode()
indent(                indexOf(               intern()               isBlank()              isEmpty()
lastIndexOf(           length()               lines()                matches(               notify()
notifyAll()            offsetByCodePoints(    regionMatches(         repeat(                replace(
replaceAll(            replaceFirst(          resolveConstantDesc(   split(                 startsWith(
strip()                stripIndent()          stripLeading()         stripTrailing()        subSequence(
substring(             toCharArray()          toLowerCase(           toString()             toUpperCase(
transform(             translateEscapes()     trim()                 wait(
jshell> "test".

メソッド

jshell> "test".toUpperCase()
$3 ==> "TEST"
jshell> Math.round(4.5)
$1 ==> 5

チェーンもOK。

jshell> "test".toUpperCase().charAt(2)
$2 ==> 'S'

変数も使えるぞ!

var [変数名] = [値]
jshell> var str1 = "ABC"
str1 ==> "ABC"

jshell> var str2 = "DEF"
str2 ==> "DEF"

jshell> str1 + str2
$5 ==> "ABCDEF"

型変換は不可能。

jshell> /var str1
|    String str1 = "abc"

jshell> str1 = 1
|  エラー:
|  不適合な型: intをjava.lang.Stringに変換できません:
|  str1 = 1
|         ^

型指定して変数宣言

jshell> String str3 = "XYZ"
str3 ==> "XYZ"

jshell> /var str3
|    String str3 = "XYZ"

配列も宣言できる。

jshell> int[] array = {1, 2, 3}
array ==> int[3] { 1, 2, 3 }

jshell> array[0]
$13 ==> 1

宣言と代入のステートメントをわけることもOK。

jshell> String str4
str4 ==> null

jshell> str4 = "QWE"
str4 ==> "QWE"

メソッドも宣言できるぞ!

int addtion(int a, int b) {
  return a + b;
}
jshell> int addtion(int a, int b) {
   ...>     return a + b;
   ...> }
|  次を作成しました: メソッド addtion(int,int)

jshell> addtion(1,3)
$21 ==> 4

エラーが有る時は、メソッドブロック最後の「}」入力した時に、エラー表示される。

jshell> int addtion(int a, int b) {
   ...>     return a + b
   ...> }
|  エラー:
|  ';'がありません
|      return a + b
|                  ^

エラーになった場合は、「上矢印キー」を入力すると、メソッドの編集モードになるので、
エラー箇所を修正する。

メソッドはまずサクラエディタなのでコーディングして、それをコピペしたほうが楽です。
※インデントでタブ文字は禁止です。タブがあるとタブコマンドと認識されてエラーになる。インデントは半角スペースで。もちろんインデント無しでもOK。

サクラエディタで

int addtion(int a, int b) {
 return a + b;
}

とコーディングして、jshellにコピペ、エンター。

jshell> int addtion(int a, int b) {
   ...>      return a + b;
   ...> }
|  次を変更しました: メソッド addtion(int,int)

ステートメントをエディタで編集

既存のメソッドを編集する時は、上記のように外部エディタからコピペでもOK。
もしくは、編集したいステートメント番号を調べて「/edit [ID]」でもデフォルトエディタが起動される。

jshell> /list

   1 : 1 + 2
   2 : int addtion(int a, int b) {
            return a + b;
       }
/edit 2

エディタが起動される。

前方参照

JShellでは、未定義のメソッド、変数またはクラスを参照するメソッド定義が使用可能。
ワーニングにはなるが、未宣言の「RATE_SALES_TAX」を使うことが出来る。

// RATE_SALES_TAX未宣言状態で参照メソッド作成
jshell> int getSalesTax(int price) {
   ...>       return (int)Math.floor(price * RATE_SALES_TAX);
   ...> }
|  次を作成しました: メソッド getSalesTax(int)。しかし、 variable RATE_SALES_TAXが宣言されるまで、起動できません

jshell> final double RATE_SALES_TAX = 0.1
RATE_SALES_TAX ==> 0.1

jshell> getSalesTax(100)
$8 ==> 10

クラスも定義できるぞ!

public class Person {
  private String name;
  public Person(final String name) {
    this.name = name;
  }
  public String getName() {
    return name;
  }
}
jshell> public class Person {
   ...>       private String name;
   ...>       public Person(final String name) {
   ...>             this.name = name;
   ...>       }
   ...>       public String getName() {
   ...>             return name;
   ...>       }
   ...> }
|  次を作成しました: クラス Person

jshell> Person aoki = new Person("AOKI");
aoki ==> Person@736e9adb

jshell> aoki.getName()
$11 ==> "AOKI"

外部モジュールもつかえるぞ!

必要なこと。

  • jshell でクラスパス指定
  • 使前にクラスをimport

ためしに、commons-lang3-3.12.0.jarのStringUtilを使ってみた。

クラスパス指定してjshell起動

外部モジュールのjarを指定。

jshell --class-path ./lib/commons-lang3-3.12.0.jar

起動した後であれば、「/env」コマンドでもOK。

jshell> /env --class-path ./lib/commons-lang3-3.12.0.jar
|  新しいオプションの設定と状態の復元。

インポート

jshell> import org.apache.commons.lang3.StringUtils;

使ってみる

jshell> StringUtils.isEmpty(null);
$2 ==> true

使えた。

複数行のステートメント

1ステートメントが長すぎて1行だと見づらい場合は、「(」を開いたままで改行するか、行の末尾を「.」で終わると複数入力可能です。

「(」を開いたままで改行

doSSometiong(A, B, C
D, E, F);

行の末尾を「.」で終わる

int sum = array.stream().
filter(element -> element.getParam1().equals("A")).
mapToInt(element -> element.getParam2()).
sum();

「.」先頭は別ステートメント扱いになりエラーになる。
サイトでのサンプルでメソッドチェーンを複数行で記載している場合、「.
」を先頭に記述しているのがほとんど。なのでコピペの際は気をつけること。

// エラーになる。
int sum = array.stream().
filter(element -> element.getParam1().equals("A"))
.mapToInt(element -> element.getParam2())
.sum();

コピペしたらエラーになった。

jshell> int sum = array.stream().
   ...> filter(element -> element.getParam1().equals("A"))
|  エラー:
|  不適合な型: java.util.stream.Stream<MyClass>をintに変換できません:
|  int sum = array.stream().
|            ^--------------...

jshell> .mapToInt(element -> element.getParam2())
|  エラー:
|  式の開始が不正です
|  .mapToInt(element -> element.getParam2())
|  ^

jshell> .sum();

編集モードを抜ける

編集モードの時、プロンプトは「...>」になっている。コピペ失敗なので編集モードを抜けたい時は、「Ctl+C」で抜ける。抜けた場合、作業中の変更は破棄されるので注意。

jshell> inat addtion(int a, int b) {
   ...> 

「Ctl+C」

jshell> inat addtion(int a, int b) {
   ...> 
jshell>    <= 抜けた   

jshellコマンド

宣言済みの変数の型と値を確認

特定のもの

/var [変数名]
jshell> /var str1
|    String str1 = "abc"

宣言済みの変数全て

/vars
jshell> /vars
|    long $1 = 5
|    char $2 = 'S'
|    String str2 = "DEF"
|    String $5 = "ABCDEF"
|    String str1 = "abc"
|    String $9 = "SSSSDEF"
|    String $11 = "abcDEF"
|    int[] array = int[3] { 1, 2, 3 }
|    int $13 = 1
|    String str3 = "XYZ"
|    String str4 = "QWE"

宣言済みのメソッドを確認

特定のもの

/method [メソッド名]
jshell> /method addtion
|    int addtion(int,int)

宣言済みのメソッド全て

/methods
jshell> /methods
|    void methodA()
|    void methodB()
|    int addtion(int,int)

削除

変数削除

/drop [変数名]
jshell> /drop str3
|  次を削除しました: 変数 str3

メソッド削除

/drop [メソッド名]
jshell> /drop methodA
|  次を削除しました: メソッド methodA()

import確認

/import
jshell> /import
|    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.*

入力したステートメント一覧

/list
jshell> /list

   1 : String str1 = "AAAA";
   2 : String str2 = "BBBB";
   3 : int addtion(int a, int b) {
            return a + b;
       }
   4 : int i1 = 1;

エラーになったステートメントとかimportとか全部の場合はallオプションを付ける。

/list -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 str1 = "AAAA";
   2 : String str2 = "BBBB";
   3 : int addtion(int a, int b) {
            return a + b;
       }
   4 : int i1 = 1;
  e1 : int i2 = "2"; <----★これエラーになったやつ

リセット

入力したステートメントを全てクリア。起動時に戻る。

/reset

リセットした直後

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.*;

コマンド一覧

jshellコマンド

タブ補完

コマンドやメソッド名は最後まで入力しなくても、何文字か入力してタブキーを押下すると補完してくれる。複数候補がある場合は、候補を表示してくれる。

jshell>  /l[タブキー]

jshell>  /list

候補が複数ある場合

jshell> me
methodA()   methosB()
jshell> metho

おまけ

jdbc疎通確認してみた

AWS Aurora Postgresqlへ接続。

ドライバークラスパス設定

jshell --class-path ./lib/postgresql-42.4.0.jar

疎通確認

正常に接続できた時。

jshell> var conn = java.sql.DriverManager.getConnection("jdbc:postgresql://sp-work.cluster-xxxxxxxxxxx.ap-northeast-1.r
ds.amazonaws.com:5432/postgres", "user", "xxxxxx");
conn ==> org.postgresql.jdbc.PgConnection@74e52303

hostが見つからなくて失敗した時。

jshell> var conn = java.sql.DriverManager.getConnection("jdbc:postgresql://sp-work.hoge.com:5432/postgres", "postgres",
"xxxxxx");
|  例外org.postgresql.util.PSQLException: 接続試行は失敗しました。
|        at ConnectionFactoryImpl.openConnectionImpl (ConnectionFactoryImpl.java:331)
|        at ConnectionFactory.openConnection (ConnectionFactory.java:49)
|        at PgConnection.<init> (PgConnection.java:223)
|        at Driver.makeConnection (Driver.java:402)
|        at Driver.connect (Driver.java:261)
|        at DriverManager.getConnection (DriverManager.java:683)
|        at DriverManager.getConnection (DriverManager.java:230)
|        at do_it$Aux (#14:1)
|        at (#14:1)
|  原因: java.net.UnknownHostException: sp-work.hoge.com
|        at NioSocketImpl.connect (NioSocketImpl.java:564)
|        at SocksSocketImpl.connect (SocksSocketImpl.java:327)
|        at Socket.connect (Socket.java:633)
|        at PGStream.createSocket (PGStream.java:241)
|        at PGStream.<init> (PGStream.java:98)
|        at ConnectionFactoryImpl.tryConnect (ConnectionFactoryImpl.java:109)
|        at ConnectionFactoryImpl.openConnectionImpl (ConnectionFactoryImpl.java:235)
|        ...

閉じる。

jshell> conn.close()
jshell>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0