はじめに
Java 25 が 2025年9月16日 に正式リリースされました🎉
Java 25 は、Java 21(2023年9月リリース)以来の長期サポート版(LTS: Long-Term Support)であり、今後も広く長く利用されることが見込まれます。
Java 25 の概要ページを見ていて、まず思ったことは「Java がモダンな言語になっている!」です。これまで「Javaは冗長」「学習コストが高い」と感じていた人ほど、驚く変更が入っています。
ご覧ください。こちらが Java の「Hello World」のビフォーアフターです。
// 従来の書き方
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
// Java 25 (Compact Source File, JEP 512)
void main() {
IO.println("Hello, World!");
}
すごい。
多くの記述が省略され、コード量が一気に減りました。これにより、Javaでも小規模なプログラムをシンプルに記述でき、開発者がより直感的にコードを書けるようになっています。
本記事では、Java のモダナイズの象徴として注目したい 3 つの JEP を紹介します。
JEP とは
JEP(JDK Enhancement Proposal)とは、Java(JDK)に新しい機能や変更を加えるための、OpenJDKにおける公式な提案書です。新しい言語機能や API、JVM の改善などは JEP として提案され、採用されたものが特定の Java バージョンに取り込まれます。
Javaに導入された言語機能
以下が、個人的に「モダンなJava」を感じる JEP です。
それでは、それぞれ詳しく見ていきます。
JEP 512: コンパクトソースファイルとインスタンスmainメソッド
JEP 512: Compact Source Files and Instance Main Methods
概要
JEP 512 は、定型的なコード記述を減らし、小さなプログラム(学習用コード、スクリプト、ユーティリティなど)をより簡潔に書けるようにするものです。Javaを始める際のハードルが下がり、学習や試行をより気軽に行えるようになります。
サンプル
従来の「Hello World」と、JEP 512による新しい書き方の比較です。
// 従来の書き方
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
// JEP 512, コンパクトソースファイル + インスタンスmain + IOクラス
void main() {
IO.println("Hello, World!");
}
特徴
以下は JEP 512 の主な仕様上の特徴です。
-
インスタンスmainメソッド
main メソッドの要件を緩和し、public static void main(String[] args)を必須とせずvoid main()/void main(String[] args)のインスタンスmainを許可する。起動時はmain(String[] args)が優先され、なければmain()が選ばれる。main()が選ばれる場合、非privateの引数なしコンストラクタが必要で、無いと起動時エラーとなる。 -
コンパクトソースファイル
クラス宣言を省略できる「コンパクトソースファイル」の導入。クラス宣言がないソースは暗黙のfinalトップレベルクラスとして扱われ、メンバはそのクラスのフィールド/メソッドになる。暗黙クラスはソースから参照できる名前を持たず、名前のないパッケージに属する。起動可能なmainを持たなければコンパイルエラーとなる。
暗黙クラスの性質
暗黙クラスは final で Object を継承し、引数なしデフォルトコンストラクタのみを持つ。クラス名はソースから参照できず、new で直接生成できない(this は使える)。
-
java.lang.IO
基本的なコンソールI/Oを簡潔に書けるjava.lang.IOの追加。print/println/readlnなどのI/Oを提供する新クラス。java.langなのでクラス自体は暗黙インポートされるが、静的メソッドは自動インポートされないため、IO.println(...)のようにクラス名で呼ぶ必要がある。 -
java.baseの暗黙インポート
コンパクトソースファイルではjava.baseをデフォルトでインポートし、Listなどの主要な型を明示的なimport文なしで利用できる。 -
スムーズな移行
プログラムが成長したら、コードを明示的なclassで囲むだけで通常のソースファイルに移行でき、mainの形は変えずに済む。
JEP 513: 柔軟なコンストラクタボディ
JEP 513: Flexible Constructor Bodies
概要
JEP 513 は、これまでコンストラクタの先頭行に super(...) / this(...) が必要だった制約を緩和し、その呼び出しより前に安全な処理(作成中インスタンスを参照しない範囲で)を記述できるようにするものです。これにより、コンストラクタでの初期化ロジックをより柔軟に表現でき、引数検証や補助計算を自然な位置に記述することで可読性が向上します。
サンプル
親クラスのコンストラクタを呼ぶ前に、引数の検証を行う例です。
public class Employee extends Person {
public Employee(int age) {
// super() の前に処理を記述できる
if (age < 18) {
throw new IllegalArgumentException("Age too young");
}
super(age);
}
}
特徴
以下は JEP 513 の主な仕様上の特徴です。
-
プロローグ/エピローグ
明示的なsuper(...)/this(...)の前後に処理を記述できる。呼び出し前がプロローグ、後がエピローグ。明示的な呼び出しがない場合は暗黙のsuper()が先頭にある扱いとなり、すべてがエピローグとなる。 -
初期構築コンテキスト(Early construction contexts)
プロローグと明示的呼び出しの引数式は初期構築コンテキストとなり、this(明示/暗黙)やインスタンスフィールド/メソッド、superによる参照が禁止(未初期化インスタンスに触れる行為は禁止)。例外として、初期化子を持たない同一クラスのフィールドへの単純代入は許可される。 -
fail-fast と安全な初期化
未初期化インスタンスへの参照など、許可されていない操作は実行時エラーではなくコンパイルエラーとなるよう設計されている。条件を満たせば、プロローグでサブクラス側のフィールドを先に初期化できる。 -
returnの扱い
returnはエピローグでのみ使用可能(式付きreturnは不可)で、プロローグには書けない。 -
互換性
既存のコンストラクタはそのまま有効で、記述の自由度だけが増える。
JEP 456: 無名変数およびパターン
JEP 456: Unnamed Variables & Patterns
概要
JEP 456 は、使用しない変数やパターンをアンダースコア(_)で表す「無名変数・無名パターン」を導入する機能です(JDK 22 で正式化)。_ は名前が無く参照できないため、意図的に未使用であることを保証できます。不要な変数名の定義を避けることで、コードの意図をより明確に表現できるようになります。
サンプル
以下は、様々な場面でアンダースコア(_)を活用している様子です。
// 1. ラムダ式の未使用パラメータ
map.forEach((k, _) -> System.out.println(k));
// 2. 例外パラメータ
try { ... } catch (Exception _) { ... }
// 3. レコードパターンでの利用(不要なコンポーネントを省略)
if (obj instanceof ColoredPoint(Point(int x, _), _)) {
System.out.println("x = " + x);
}
特徴
以下は JEP 456 の主な仕様上の特徴です。
-
意図の明確化と安全性
_は、スコープに名前を置かないため宣言後に参照できず、同一スコープで何度でも使える(変数のシャドウイングが起きない)。また未使用であることがコンパイル時に保証される。 -
適用範囲
_は、ローカル変数宣言、try-with-resources、基本/拡張for、catch、ラムダ式のパラメータに使える。ローカル変数宣言やtry-with-resources では初期化が必須。また、フィールドやメソッド引数には使えない。 -
無名パターン
型パターンの変数名を_にでき(Type _)、さらに_単体はvar _と同等の「無名パターン」としてレコードパターン内のみで使える(トップレベルのinstanceofやcaseでは不可)。 -
caseラベルの統合
名前付きのパターン変数を宣言しないパターンに限り、複数パターンを1つのcaseにまとめられる(名前付きの束縛がないパターンならまとめられる)。 -
歴史的背景
単独の_は Java 8 で警告、Java 9 でエラーとなり、JEP 456 で「無名」として再定義された。_ageや__などの識別子は引き続き有効。
さいごに
今回のアップデートで、Javaが「大規模システム」向け言語にとどまらず、「小さく作って学び、育てていく」言語として扱えるようになってきたことが分かりました。単なる記法の短縮ではなく、学習のしやすさ・安全性・可読性が改善され、さらに後方互換性も保たれています。
ぜひ本記事をきっかけに、改めて Java に触れていただけるとうれしいです!