Edited at
JavaDay 25

【Java11】javacでコンパイルせずにJavaを実行してみた


はじめに

本投稿はJava Advent Calendar 2018 の25日目の記事です。

初心者ではありますが、「参加することに意義がある!」の精神で、とりあえず空いていた枠に登録してしまいました。

最終日にも関わらず、薄い内容で申し訳ない気持ちもありますが初心者らしく、いざHelloWorld!

 ※2018/12/26更新:サ〇タ業務の都合上、書きかけで投稿してしまったため、一部内容を追加。


コンパイルせずにjavaを実行!?

Java11から、javacでコンパイルせずにjavaを実行できるという噂を聞きつけたため、HelloWorldしてみる。

ただし、ソースファイルが1つで完結する場合に限るなどの制限があるようなので、その辺も試してみる。


環境

OS:Windows 10

Java:Oracle Open JDK 11

コンソール:コマンドプロンプト


まずは普通のHelloWorldのみ

HelloJDK11.java

public class HelloJDK11 {

public static void main(String[] args) {
System.out.println("HelloWorld!");
}
}

実行してみる

>java HelloJDK11.java

HelloWorld!


めでたく、コンパイルせずに実行できました。

HelloJDK11.javaが存在するディレクトリには、HelloJDK11.classは作成されていませんでした。


試しにjavacでコンパイルしてみる

>javac HelloJDK11.java

>java HelloJDK11
HelloWorld!

いつも通り、HelloJDK11.classが作成されました。


しかし、、、

>java HelloJDK11.java

エラー: アプリケーション・クラス・パスにクラスが見つかりました: HelloJDK11

どうやら、クラスパス上にclassファイルが存在する場合、javaファイルをjavaコマンドで実行するとエラーとなるようです。

classファイルを削除すると、元通りjava HelloJDK11.javaで実行可能になりました。


念のためにメソッド呼び出しをする

public class HelloJDK11 {

public static void main(String[] args) {
System.out.println("HelloWorld!");
callMethod();
}

private static void callMethod() {
System.out.println("CalledMethod!");
}
}

実行

>java HelloJDK11.java

HelloWorld!
CalledMethod!

メソッド呼び出しも問題ありませんでした。

 ※先ほど作成されていたclassファイルは削除しています。


javaファイル名とクラス名を別名にする

HelloJDK11.java

public class SorryJDK11 {

public static void main(String[] args) {

~先ほどと同様なので略~

}

javaファイル名:HelloJDK11.java

クラス名:SorryJDK11

実行とコンパイル

>java HelloJDK11.java

HelloWorld!
CalledMethod!

>javac HelloJDK11.java
HelloJDK11.java:1: エラー: クラス SorryJDK11はpublicであり、ファイルSorryJDK11.javaで宣言する必要があります
public class SorryJDK11 {
^
エラー1個

javaファイル名とクラス名が不一致だと、


コンパイル出来ないが、javaファイルのまま実行可能なようです。


Personクラスを書いてnewしてみる

HelloJDK11.java

public class HelloJDK11 {

public static void main(String[] args) {
Person suzuki = new Person("鈴木");
System.out.println(suzuki.getName());
}
}

class Person {
// フィールド
private String name;
// コンストラクタ
public Person(String name) {
this.name = name;
}
// ゲッター
public String getName() {
return this.name;
}
}

実行

> java HelloJDK11.java

鈴木

問題ありませんでした。


Personクラスを別ファイルに分割する

先ほどのHelloJDK11.javaをHelloJDK11.javaとPerson.javaの2ファイルに分割

>java HelloJDK11.java

HelloJDK11.java:7: エラー: シンボルを見つけられません
Person suzuki = new Person("鈴木");
^
シンボル: クラス Person
場所: クラス HelloJDK11
HelloJDK11.java:7: エラー: シンボルを見つけられません
Person suzuki = new Person("鈴木");
^
シンボル: クラス Person
場所: クラス HelloJDK11
エラー2個
エラー: コンパイルが失敗しました

コンパイルエラーが発生しました!


冒頭でも記述した制限事項

「1つのソースファイルで完結している必要がある。」による

コンパイルエラーが発生しました。


一応、javacでコンパイルすると、

>javac HelloJDK11.java

HelloJDK11.classとPerson.classの2ファイルが作成され、javaコマンドで実行も出来ました。


まとめ

新人研修の頃、毎回javacしてjavaしてたのが面倒だった記憶があるため、今回のJava11でのjavacなしで実行できるという動作に興味を持ち記事にしてみました。

JEP 330によると、別にJavaをスクリプト言語のようにコンパイルなしで実行できるようにすることが目的ではないようです。

シェバン(shellの1行目の#!/bin/shとか)としてJavaファイルをコマンド実行することが目的とのこと。

./HelloJDK11

みたいに実行できるらしいです。(今度試してみます。)