Java SE11 Silver の試験問題を確認していて、Java11からはコンパイルしなくても実行できるパターンがあることを知りました。
ただし、ソースファイルが1つのみで実行できる(他のファイルのクラスを呼び出さない)場合に限る等の制限もあるようなので確認してみたいと思います。
環境
今回試した環境は以下の通りです。
OS : macOS Big Sur(バージョン 11.0.1)
コンソール : iTerm2
とりあえず画面表示をしてみる
文字列を画面表示するだけの簡単なプログラムを書いてみます。
public class Test11 { public static void main(String[] args) { System.out.println("Java11!"); } }
では実行してみます。
$ java Test11.java Java11!
実行できました!
もちろん「Test11.class」は作成されていませんでした。
本当にコンパイル無しでも実行できるようになったのですね。
今まで通り、コンパイルしてから実行して見る
javac コマンドを使ってコンパイルしてから実行して見ます。
$ javac Test11.java $ java Test11 Java11!
今まで通り「Test11.class」が作成され、javaコマンドで実行も出来ました。
ここで問題発生
再度先ほどと同様に「java Test11.java」を実行するとエラーになりました。
$ java Test11.java エラー: アプリケーション・クラス・パスにクラスが見つかりました: Test11
どうやら、「アプリケーション・クラス・パス」上にclassファイルが存在する場合に、javaファイルをjavaコマンドで実行するとエラーとなるようです。
classファイルを削除すると、「java Test11.java」で実行可能になりました。
メソッドも使って見る
メソッドを追加して、呼び出してみます。
public class Test11 { public static void main(String[] args) { System.out.println("Java11!"); callMethod(); } public static void callMethod() { System.out.println("Method Call OK!!"); } }
実行します。
$ java Test11.java Java11! Method Call OK!!
出来ました!
問題無くメソッドの呼び出しも出来ますね。
クラス名とファイル名を異なる名前にしてみた
これはちょっと変わった(私が思っているだけ?)動きになりました。
まず、ファイル名は「Test11.java」のまま、クラス名を「ChangeTest11」へ変更しました。
public class ChangeTest11 { public static void main(String[] args) { System.out.println("Java11!"); callMethod(); } public static void callMethod() { System.out.println("Method Call OK!!"); } }
実行して見ます。
$ java Test11.java Java11! Method Call OK!!
問題無く実行できます。
今度はコンパイルしてみます。
$ javac Test11.java Test11.java:1: エラー: クラス ChangeTest11はpublicであり、ファイルChangeTest11.javaで宣言する必要があります public class ChangeTest11 { ^ エラー1個
コンパイルはエラーになってしまいますね。(これは今まで通り)
クラスを追加してみる
「Test11.java」ファイルの中にクラスを追加し、使用してみます。
public class Test11 { public static void main(String[] args) { Car honda = new Car("Honda"); System.out.println(honda.getName()); } } class Car { private String name; Car(String name) { this.name = name; } public String getName() { return this.name; } }
実行して見ます。
$ java Test11.java Honda
実行できました。
クラスが複数あっても問題無く実行できますね。
別ファイルにあるクラスを呼び出してみる
ファイルが1つの場合のみ実行できるという事なので、別ファイルにクラスが定義されていた場合には実行できないはずですので、確認して見ます。
1つ目の「Test11.java」
public class Test11 { public static void main(String[] args) { Car honda = new Car("Honda"); System.out.println(honda.getName()); } }
2つ目の「Car.java」
class Car { private String name; Car(String name) { this.name = name; } public String getName() { return this.name; } }
実行して見ます。
$ java Test11.java Test11.java:3: エラー: シンボルを見つけられません Car honda = new Car("Honda"); ^ シンボル: クラス Car 場所: クラス ChangeTest11 Test11.java:3: エラー: シンボルを見つけられません Car honda = new Car("Honda"); ^ シンボル: クラス Car 場所: クラス ChangeTest11 エラー2個 エラー: コンパイルが失敗しました
想定通り、コンパイルエラーになりました。
念のためコンパイルしてから実行してみます。
$ javac Test11.java $ java Test11 Honda
コンパイルしてからであれば実行可能です。
まとめ
今までちょっとした簡単なプログラムでも、「コンパイル」→「実行」という流れを取らなくてはならず少々面倒な場面もありましたが、これで少しは楽が出来そうですね。