Javaがパブリックスタティックヴォイドメインの呪文から解放される

みなさん、今日もパブリックスタティックヴォイドメインしてますか?
ジャバと言えばパブリックスタティックヴォイドメインですよね。
最近はIDEmain[tab]と入力すれば補完してくれるとはいえ、コードを読むときには目に入ってきたりしますね。
そんなパブリックスタティックヴォイドメインの呪文から解放される日が近づいています。

TL; DR

9月リリースのJava 21の試用機能として

void main() {
  System.out.println("Hello");
}

をhello.javaで保存したら、java hello.javaで実行できるようになります。
(Java 21では--enable-preview --source 21が必要)

Javaではプログラムを開始するときにpublicclassなどにStringの配列を受け取るpublicstaticで戻り値を返さないmainという名前のメソッドを定義する必要があります。

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

最低限必要なのは この部分だけなのに、いろいろついています。

println("Hello Java!");

これが問題なのは、Javaプログラミングの開始時に教えないといけないことが多すぎるということです。クラス、アクセス指定、static、メソッド定義、引数、String、配列、クラスメンバー、インスタンスメンバー、メソッド呼び出しを知っておく必要があります。
この中で、メソッド呼び出しは機能実現に必要であるし、メソッド定義も結局早い時期に必要になるのであってもいいと思います。クラスも、まあそういう方針として許容範囲。
しかし、アクセス指定は複数のクラスを定義しないと説明ができません。そしてstaticはインスタンスを説明しないといけないし、staticなしのメンバーとのやりとりの説明がかなり大変です。配列も割と面倒。

ということで、9月リリース予定のJava 21から試用機能として次のように書けます。

void main() {
  System.out.println("Hello Java");
}

JEP 445としてまとめられています。
JEP 445: Unnamed Classes and Instance Main Methods (Preview)

JEP 445は先週のBuild 26で取り込まれて使えるようになっています。
https://jdk.java.net/21/

これを実行するには、次のように--enable-preview--sourceの指定が必要です。

> java --source 21 --enable-preview hello.java
ノート: hello.javaはJava SE 21のプレビュー機能を使用します。
ノート: 詳細は、-Xlint:previewオプションを指定して再コンパイルしてください。
Hello Java

一旦コンパイルする場合は、javaコマンドには--sourceは不要です。ソースファイル名と同じ名前のclassファイルができます。

>javac --enable-preview --source 21 hello.java
ノート: hello.javaはJava SE 21のプレビュー機能を使用します。
ノート: 詳細は、-Xlint:previewオプションを指定して再コンパイルしてください。

> java --enable-preview hello
Hello Java

けどまあ、コマンドラインで動かすときにわざわざコンパイルは しないですね。

クラスが書きたいならこれでもOKです。

class Hello {
  void main() {
    System.out.println("Hello Java");
  }
}

つまり、アクセス指定はprivate以外ならなんでもいい、mainString[]引数があってもなくてもいい、staticでもstaticじゃなくてもいい、クラスもあってもなくていい、ということになっています。
クラスがない場合は、実際にはObjectの匿名クラスということになります。

new Object() {
  void main() {
    System.out.println("Hello Java");
  }
}.main();

で、クラスとかstaticとか不要なのが、サンプルプログラムを書くのにとてもいいです。逆にいえば、いままでパブリックスタティックヴォイドメインはかなり邪魔になっていたということです。

高度に発展したジャヴァプログラマーにとってパブリックスタティックヴォイドメインは自動的に視界から消えていたわけですが、実際に消えたところを見ると、やっぱ全然違いますね。
これは、高度に発展したジャヴァプログラマーにとって匿名クラスは自動的にクロージャに見えていたのが、ラムダ式が導入されるとやっぱ邪魔だったというのと同じですね。

まあ、高度に発展したジャヴァプログラマーは誤魔化せるとしても、紙の雑誌の文字数は誤魔化せないのですね。
クラス定義でどんどん紙を圧迫してしまうので、完全な形のコードは気軽には示せず、クラスやmainを省略した形で載せることになっていました。その場合にpublic static void main(String[])を出してしまうと、言いたいことが隠れるので結局はコード部分だけ載せることになってました。

それが、たとえばStreamの説明でも次のコードでちゃんと動かせるプログラムとして提示できるわけです。

import java.util.stream.Stream;
void main() {
  Stream.of("apple", "banana")
    .map(String::toUpperCase)
    .forEach(s -> System.out.println(STR."これは\{s}です"));
}

クラスのimportとそれを使うコードが近くなるのでとてもいい。
あと、文字列に値を埋め込めるString Templateもいいですね。これもJava 21で試用機能として導入されます。
JEP 430: String Templates (Preview)

パブリックスタティックヴォイドメインがなくなると、ジャバに見えなくなります。
あとはSystem.outにジャバらしさが残りますが、これも恐らくそのうち消せます。
System.out.printlnをデフォルトのstatic importにしようという話をしています。というか、今回のJEP 445は次の「入口の舗装」という話の一部になっています。
Paving the on-ramp

去年の9月に話が出てきて今年の9月に実装されるというスピード感、いかにPythonのプレッシャー感じてるかがわかりますね。

ということで、6月24日発売のWEB+DB PRESS Vol.135でのサンプルコードはほとんどすべてvoid main()で囲んで書いています。ほかにもJava 21の機能を活かしながらサンプルを書いているので見てみてください。
コレハジャバデハナイとなります。
主題は、プログラムの処理をどう考えるかという話なので、ジャバじゃない人も読んでください。

※追記 19:35 JEP443にしてたのを、JEP445に修正しました。
あと、「プロジェクトに1回書けばいい」というコメントありますが、入門時には1ページに1回書いたりします。1時間の授業で3つ4つ書くこともありますね。それと、staticは入門時に非常に邪魔なのでなくなってありがたい。
C#がプレッシャ与えるほど追い上げているような気配はないし、C#対抗であればエントリポイント改善は有効ではないと思います。

※追記 20:58 シンタックスシュガーは覚えることが増えるという話ありますが、覚えるタイミングの問題です。入門したてで何もわからんときにいきなり覚えることが多すぎて、「見なかったことにして」と言わざるをえないのは教えるうえで結構な障害になります。あとstaticと非staticの使い分けがかなりやっかいです。
ある程度プログラミングを理解してから教えることができるようになるのは、とてもやりやすいです。