未来エンジニア養成所Blog

プログラミングを皆に楽しんでもらうための情報をお届けします。

コンパイルをせずにJavaのプログラムを実行する

Java SE11 Silver の試験問題を確認していて、Java11からはコンパイルしなくても実行できるパターンがあることを知りました。

ただし、ソースファイルが1つのみで実行できる(他のファイルのクラスを呼び出さない)場合に限る等の制限もあるようなので確認してみたいと思います。


環境

今回試した環境は以下の通りです。


OS : macOS Big Sur(バージョン 11.0.1)

Java : Open JDK 11.0.9

コンソール : 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

コンパイルしてからであれば実行可能です。

まとめ

今までちょっとした簡単なプログラムでも、「コンパイル」→「実行」という流れを取らなくてはならず少々面倒な場面もありましたが、これで少しは楽が出来そうですね。





オンラインプログラミングスクール
未来エンジニア養成所Logo