はじめに
皆さん、お風呂は好きですか?私は好きです。暖かいお風呂に浸かってリラックスする時間は良いものです。
不思議なもので、プログラミングから離れて別のことをしている時、プログラミングに関して何か閃くことってありますよね。今回もそうでした。
ある日、いつものようにお風呂に浸かってボーッとしていた時、突然閃きました。「JShellってJavaコードが書かれたファイルを読み込んで、その内容を実行させることはできるのだろうか?」「それができるのであれば、スクリプトのようにJavaコードを実行できるんじゃね?」って。
世の中にはお風呂に浸かりながらプログラミングする方もいらっしゃるそうですが、あいにく私はその域には達していないので、すぐに試すことはできません。仕方ないので、閃いたことを忘れないように意識しながら早めにお風呂場を出ました。
試す
部屋着を着て、MacBookを開き、それっぽいキーワードでググります。はたして、JShellはJavaコードが書かれたファイルを読み込んで、その内容を実行させることが可能であるようです。早速試してみます。
JShellを使うので、以降のサンプルはJava9以上でないと実行できません。あしからず。
コード
System.out.println("Kitty on your lap")
/ex
JShellなのでコードはこれだけで済みます。セミコロンも不要です。 /ex
はJShellの終了コマンドで、これがないとJShellの対話式実行の状態になってしまうとのことです。
実行
jshell test.jsh
jshell
コマンドにファイル名を渡すだけで実行できます。
Enter を押してから実行されるまでにちょっと時間がかかりましたが、これだけでちゃんと「Kitty on your lap」が表示されました。素晴らしいですね。
なお、ファイルの拡張子は後掲の参考リンクに倣って.jshとしましたが、他の拡張子でも動作するようです。なんなら.javaでもいいです。(紛らわしいですが…)
メリット
さて、この実行方法はJShellを使っているわけなので、JShell自体のメリットがそのままこの実行方法のメリットになるはずです。つまり、下記のようなメリットがあります。
(タブ補完のような、JShell上で直接実行する場合のメリットは除く)
-
javac
でコンパイルするといった手順なしで実行できる - クラスとmainメソッドを書かなくてもJavaコードを実行できる
- 行末のセミコロンを省略可能
- よく使うパッケージについてはインポート済でそのまま使える(java.io.* や java.util.* など)
- チェック例外を無視できる
素晴らしいですね。(語彙力)
風呂上がりでただでさえ火照っている胸がさらに熱くなりました。
もうちょっと試す
上記の4つ目や5つ目のメリットは前掲のサンプルでは確認できないので、別の例を書いてみます。
テキストファイルを読み込んで、「hoge」が含まれる行を表示するコードです。
try(Stream<String> lines = Files.lines(Paths.get("test.txt"))) {
lines.filter(line -> line.contains("hoge"))
.forEach(System.out::println);
}
/ex
Stream、Files、Pathsについて、明示的にインポートしなくても使えています。また、Files.lines()はIOExceptionを投げる可能性がありますが、IOExceptionを処理するコードを書かなくても動作しています。Javaにしては短く書けてなかなかいい感じです。
ただ、この例だとセミコロンを省略できないようでした。(エラーとなりました。たぶん内部的なコンパイル時のエラー)
デメリット
体が冷えるにつれ、頭のほうも冷静になってきました。
Javaにしては短く書けて明示的なコンパイルなしで実行できるとはいえ、コードの短さや実行の手軽さという点ではPythonやRubyといったスクリプト言語には敵いません。
また、詳細は後掲の参考リンク先を読んでいただいたほうがよさそうですが、普通に java
コマンドで実行するのと比べるとパフォーマンスの面で不利とのことです。
そうなると、あまりユースケースが思いつかないですね。ほとんどの場合はスクリプト言語を使ったほうがいいでしょうし、Javaのちょっとした動作確認のためにスニペットを実行する場合はJShell上での直接入力で事足りる場合が多いでしょうし。
Javaしか書けない人や、何かJavaにこだわりがある人がスクリプトを書きたい場合には使えるでしょうか。そのようなニッチな需要しかカバーできないのが大きなデメリットでしょうね…
まとめ
- Java9以上なら、JShellを使うことでJavaコードをスクリプト的に実行可能
- (明示的な)コンパイルが不要
- 普通にJavaを書くのに比べると短く書ける
- クラスやmainメソッドを省略可能
- セミコロンを省略可能(省略できない場合もある)
- よく使うパッケージは明示的にimportしなくてもそのまま使える
- チェック例外を処理するコードを省略可能
-
普通にPythonやRuby等を使えばいいと思う何かスクリプトを書く時に、どうしてもJavaで書きたい or そもそもJavaしか書けないという場合は重宝するかも
参考リンク
余談
- Java11以上なら、通常のJavaソースを
java
コマンドで直接実行可能とのこと - お風呂に浸かりながら寝るのは危険です。疲れがたまっている方は気をつけましょう
- お風呂に浸かりながらプログラミングするのは危険です。やるなら自己責任で