1.はじめに
2018年9月にリリースされたJavaSE11の実装であるJDK11。
このチュートリアルでは、単一ファイルのソースコードプログラムを起動するJava11の新機能について説明します。
2. Java11より前
単一ファイルプログラムは、プログラムが単一のソースファイルに収まるプログラムです。
Java 11より前は、単一ファイルのプログラムであっても、プログラムを実行するには2段階のプロセスに従う必要がありました。
たとえば、HelloWorld.javaというファイルにmain()メソッドを持つHelloWorldというクラスが含まれている場合、最初にそれをコンパイルする必要があります。
$ javac HelloWorld.java
これにより、次のコマンドを使用して実行する必要があるクラスファイルが生成されます。
$ java HelloWorld Hello Java 11!
このようなプログラムは、Javaの学習の初期段階、または小さなユーティリティプログラムを作成する場合の標準です。このコンテキストでは、実行する前にプログラムをコンパイルする必要があるのは少し儀式的です。
しかし、代わりにワンステップのプロセスがあるのは素晴らしいことではないでしょうか?Java 11は、このようなプログラムをソースから直接実行できるようにすることで、これに対処しようとします。
3.単一ファイルのソースコードプログラムの起動
Java 11以降では、次のコマンドを使用して単一ファイルプログラムを実行できます。
$ java HelloWorld.java Hello Java 11!
JavaクラスではなくJavaソースコードファイル名をjavaコマンドに渡した方法に注目してください。
JVMは、ソースファイルをメモリにコンパイルしてから、最初に見つかったpublic main()メソッドを実行します。
ソースファイルにエラーが含まれている場合はコンパイルエラーが発生しますが、それ以外の場合は、すでにコンパイルされているかのように実行されます。
4.コマンドラインオプション
Javaランチャーは、この機能をサポートするために新しいソースファイルモードを導入しました。次の2つの条件のいずれかが当てはまる場合、ソースファイルモードが有効になります。
- コマンドラインの最初の項目の後にJVMオプションが続くのは、拡張子が.javaのファイル名です。
- コマンドラインには、–sourceversionオプションが含まれています
ファイルがJavaソースファイルの標準の命名規則に準拠していない場合は、–sourceオプションを使用する必要があります。このようなファイルについては、次のセクションで詳しく説明します。
元のコマンドラインでソースファイルの名前の後に配置された引数は、実行時にコンパイル済みクラスに渡されます。
たとえば、Additionクラスを含むAddition.javaというファイルがあります。このクラスには、引数の合計を計算するmain()メソッドが含まれています。
$ java Addition.java 1 2 3
また、ファイル名の前に–class-pathなどのオプションを渡すことができます。
$ java --class-path=/some-path Addition.java 1 2 3
これで、実行しているクラスと同じ名前のクラスがアプリケーションのクラスパスにある場合、エラーが発生します。
たとえば、開発中のある時点で、javacを使用して現在の作業ディレクトリにあるファイルをコンパイルしたとします。
$ javac HelloWorld.java
これで、HelloWorld.javaとHelloWorld.classの両方が現在の作業ディレクトリに存在します。
$ ls HelloWorld.class HelloWorld.java
ただし、ソースファイルモードを使用しようとすると、エラーが発生します。
$ java HelloWorld.java error: class found on application class path: HelloWorld
5.シバンファイル
macOSやLinuxなどのUnix派生システムでは、「#!」を使用するのが一般的です。実行可能スクリプトファイルを実行するためのディレクティブ。
たとえば、シェルスクリプトは通常次のように始まります。
#!/bin/sh
次に、スクリプトを実行できます。
$ ./some_script
このようなファイルは「シバンファイル」と呼ばれます。
これで、これと同じメカニズムを使用してJava単一ファイルプログラムを実行できます。
ファイルの先頭に以下を追加すると、次のようになります。
#!/path/to/java --source version
たとえば、のは、名前のファイルに次のコードを追加してみましょう追加:
#!/usr/local/bin/java --source 11 import java.util.Arrays; public class Addition { public static void main(String[] args) { Integer sum = Arrays.stream(args) .mapToInt(Integer::parseInt) .sum(); System.out.println(sum); } }
そして、ファイルを実行可能としてマークします。
$ chmod +x add
次に、スクリプトのようにファイルを実行できます。
$ ./add 1 2 3 6
ランチャーを明示的に使用して、shebangファイルを呼び出すこともできます。
$ java --source 11 add 1 2 3 6
-sourceオプションは、それが既にファイル内に存在だ場合でも必要です。ファイル内のシバンは無視され、拡張子が.javaのない通常のJavaファイルとして扱われます。
ただし、有効なシバンが含まれている場合でも、.javaファイルをシバンファイルとして扱うことはできません。したがって、次の場合はエラーが発生します。
$ ./Addition.java ./Addition.java:1: error: illegal character: '#' #!/usr/local/bin/java --source 11 ^
シバンファイルについて最後に注意すべきことは、ディレクティブによってファイルがプラットフォームに依存するようになることです。このファイルは、ネイティブでサポートされていないWindowsなどのプラットフォームでは使用できません。
6.結論
この記事では、Java11で導入された新しい単一ファイルのソースコード機能について説明しました。
いつものように、コードスニペットはGitHubにあります。