「Javaは古い」「冗長で書くのが面倒」——そんなイメージを持っている方は少なくないと思います。正直なところ、自分も数年前まではそう感じていました。でも最近のJavaは本当に変わっていて、Java.evolvedというプロジェクトがその変化をとても分かりやすくまとめてくれています。

Java.evolvedは、古い書き方と新しい書き方をビフォー・アフター形式で比較してくれるリファレンスサイトです。Hacker Newsでも話題になっていたので、気になるポイントを紹介してみます。

Hello Worldが2行になった

Javaといえば、Hello Worldを書くだけでクラス定義とmainメソッドの5行が必要でした。これがモダンJavaでは2行で済むようになっています。

以前のコード:

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

モダンJava:

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

クラス宣言もString[]引数もSystem.out.printlnも不要になりました。学習のハードルが一気に下がりますよね。これはJEP 477(Implicitly Declared Classes and Instance Main Methods)によるもので、スクリプト的な用途にもJavaが使いやすくなっています。

パターンマッチングが超強力に

個人的にモダンJavaで一番インパクトが大きいと感じているのが、パターンマッチングの進化です。以前はinstanceofチェックの後にキャストが必要でした。

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

今はこう書けます。

if (obj instanceof String s) {
    System.out.println(s.length());
}

switch式と組み合わせると、型ごとの処理分岐がとてもすっきり書けるようになりました。

String format(Object obj) {
    return switch (obj) {
        case Integer i -> "int: " + i;
        case Double d  -> "double: " + d;
        case String s  -> "str: " + s;
        default        -> "unknown";
    };
}

sealed classesと組み合わせれば、defaultケースすら不要になります。コンパイラが網羅性を保証してくれるので、バグの温床だった「else句の書き忘れ」が構造的に防げるのは大きいですね。

レコードクラスで不変データがシンプルに

DTOやバリューオブジェクトを作るたびにgetter、equals、hashCode、toStringを書いていた時代は終わりました。レコードクラスなら1行で済みます。

record Point(int x, int y) {}

これだけで不変フィールド、コンストラクタ、アクセサメソッド、equals/hashCode/toStringが自動生成されます。Lombokに頼らなくても良くなったのは地味に大きな変化だと感じています。

テキストブロックとモジュールインポート

複数行の文字列がテキストブロックでスッキリ書けるようになったのも見逃せません。

String json = """
        {
            "name": "Java",
            "version": 24
        }
        """;

モジュールインポート宣言を使えば、大量のimport文を1行にまとめられます。

import module java.base;

java.util、java.io、java.nioなどの主要パッケージが一括でインポートされます。ファイル冒頭のimportの山が消えるのは精神衛生上とても良い変化でした。

ガードパターンでswitch文がさらに柔軟に

switch文でwhen句を使った条件分岐ができるようになりました。

return switch (shape) {
    case Circle c when c.radius() > 10 -> "large circle";
    case Circle c -> "small circle";
    default -> "not a circle";
};

以前ならif-else文のネストが必要だった処理が、宣言的に書けるようになっています。コードの可読性が格段に上がりますよね。

他の言語との比較

こうしたモダンJavaの機能は、他の言語で先行していたものが多いのは事実です。パターンマッチングはRustのような言語から影響を受けていますし、簡潔な構文はBunDenoなどのモダンランタイムにも通じるものがあります。

ただし、Javaの場合は後方互換性を維持しながら段階的に機能を追加している点が特徴的です。既存の巨大なコードベースを壊さずにモダン化できるのは、エンタープライズ環境では非常に重要なポイントだと思います。

まとめ

Java.evolvedを見ていると、「Javaは古い」というイメージがいかに時代遅れかが分かります。パターンマッチング、レコードクラス、テキストブロック、簡潔なmainメソッドなど、モダンJavaは想像以上に書きやすくなっていました。

とくに業務でJavaを使っている方は、最新バージョンの機能を一度チェックしてみる価値があると思います。Java.evolvedのサイトはビフォー・アフター形式で直感的に理解できるので、キャッチアップの入口としておすすめです。

参考リンク: