JEP 512: Compact Source Files and Instance Main Methods

blog1.mammb.com


はじめに

伝統的な Hello,World プログラムは

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

JDK 25 では以下のように書くことができます。

void main() {
    IO.println("Hello, World!");
}


JEP 512: コンパクト・ソース・ファイルとインスタンス・メイン・メソッド

JEP 512 は初心者がJava言語を段階的に学習しやすくするための提案です。 正式リリースまでJEPの名前がころころ変わり、JDK 25 で正式リリースとなります。

  • JDK 21 - JEP 445: Unnamed Classes and Instance Main Methods (Preview)
  • JDK 22 - JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
  • JDK 23 - JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview)
  • JDK 24 - JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview)
  • JDK 25 - JEP 512: Compact Source Files and Instance Main Methods

JEP 512 は以下の3つの要素で構成されます。

  • インスタンス・メイン・メソッド(Instance Main Methods)
  • コンパクト・ソース・ファイル(Compact Source Files)
  • コンソール・インタラクション(Interacting with the console)

以下にそれぞれ見ていきます。


インスタンス・メイン・メソッド

インスタンス・メイン・メソッドは、アプリケーションのエントリポイントとして伝統的なpublic static void main(String[] args) を以下のように定義できるようにしたものです。

void main() { }

インスタンス・メイン・メソッドはJavaランチャーにより以下の流れで選択されます。

  • クラスが String[] パラメーターを持つメイン・メソッドを宣言または継承している場合、ランチャーはそのメソッドを選択
  • そうでない場合、クラスがパラメーターを持たないメイン・メソッドを宣言または継承していれば、ランチャーはそのメソッドを選択
  • そうでない場合、ランチャーはエラーを報告して終了する

選択されたメソッドは以下のように実行されます。

  • 選ばれたメソッドが static であれば、ランチャーはそのメソッドを呼び出す
  • そうでない場合、選ばれたメソッドはインスタンスのメイン・メソッドとなる
    • ランチャーはそのコンストラクタ(クラスには、パラメーターを持たない非プライベート・コンストラクターがなければならない)を起動し、生成されたオブジェクトの選択されたメイン・メソッドを起動
    • そのようなコンストラクタがない場合、ランチャーはエラーを報告して終了する


コンパクトソースファイル

クラス宣言で囲まれていないフィールドやメソッドを含むソース・ファイルがあった場合、フィールドやメソッドをメンバとするクラスを暗黙的に宣言しているとみなすようになります。 このようなソース・ファイルはコンパクト・ソース・ファイルと呼ばれます。

コンパクト・ソース・ファイルの暗黙の宣言クラスは以下のようになります。

  • 無名パッケージのfinalなトップレベルクラスとなる
  • java.lang.Object を拡張し、インターフェイスを実装していない
  • パラメータの無いデフォルトのコンストラクタを持ち、他のコンストラクタは持たない
  • コンパクト・ソース・ファイルにあるフィールドとメソッドをメンバとして持つ
  • インスタンス・メイン・メソッドや通常のメインメソッドが必要

コンパクト・ソース・ファイルは以下のように定義できます。

String greeting() { return "Hello, World!"; }

void main() {
    System.out.println(greeting());
}

フィールドを使うこともできます。

String greeting = "Hello, World!";

void main() {
    System.out.println(greeting);
}
  • コンパクト・ソース・ファイルは暗黙的にクラスを宣言するので、そのクラスはソース・コードで使用できる名前を持たない(コンパイルするときにクラス名を生成するが、その名前は実装固有のものとなる)。
  • this にてクラスの現在のインスタンスを参照することができるが、new演算子を使ってクラスをインスタンス化することはできない
  • ソース・コード・ランチャーを使ってコンパクト・ソース・ファイルを直接実行することも、明示的にコンパイルしてから実行することもできる
  • javadocツールでコンパクト・ソース・ファイルからドキュメントを生成することができる(コンパクト・ソース・ファイルは他のクラスから参照されるべきではなく、API定義に意味は無いが、javadoc について学ぶ初心者の学習になる)


コンソール・インタラクション

初学者にとって、コンソールとやりとりするプログラムは概念的に重いため、java.lang.IO というクラスが追加され、以下の5つの静的メソッドが利用できるようになりました。 IOクラスは java.lang パッケージにあるので、インポートなしで使うことができます。

  • public static void print(Object obj);
  • public static void println(Object obj);
  • public static void println();
  • public static String readln(String prompt);
  • public static String readln();

コンソール出力は以下のように簡単に書けるようになります。

void main() {
    String name = IO.readln("Please enter your name: ");
    IO.print("Pleased to meet you, ");
    IO.println(name);
}

通常のプログラムから使うこともできます。

class Hello {
    public static void main(String[] args) {
        String name = IO.readln("Please enter your name: ");
        IO.print("Pleased to meet you, ");
        IO.println(name);
    }
}