CodeGym /コース /JAVA 25 SELF /新機能でよくある誤りの解説

新機能でよくある誤りの解説

JAVA 25 SELF
レベル 65, レッスン 4
使用可能

1. パターン変数のスコープに関するミス

最もよくあるミスの一つは、pattern で宣言した変数(例えば String の s を instanceof String s で導入したもの)を、その有効範囲の外で使おうとすることです。

例

Object obj = "こんにちは、Java!";
if (obj instanceof String s) {
    System.out.println(s.length());
}
// エラー!s はここでは可視ではありません
System.out.println(s); // コンパイラがエラーを出します: cannot find symbol

なぜそうなる?
pattern 変数(ここでは s)は、条件が真になるブロックの内側にだけ存在します。これは、変数が未定義のとき(例えば obj が文字列ではない場合)に、うっかり使用してしまうのを防いでくれます。

たとえ話
友だちから車の鍵を借りるのは「ガレージの中にいる間だけ」のようなものです。ガレージを出たら、鍵は自動的に消えるのと同じです :)

2. null に関するミス

instanceof の pattern matching には面白い特徴があります。オブジェクトが null の場合、結果は常に false となり、pattern 変数は生成されません。

例

Object obj = null;
if (obj instanceof String s) {
    // このブロックは決して実行されません!
    System.out.println("これは文字列です: " + s);
}

なぜ?
null はどの型(Object でさえも)のインスタンスでもありません。pattern matching で null を捕まえられると期待していると、混乱のもとになります。

正しい書き方

if (obj == null) {
    System.out.println("これは null です!");
} else if (obj instanceof String s) {
    System.out.println("これは文字列です: " + s);
}

switch の pattern matching(Java 21+)では、null 用の専用分岐を追加することもできます。

switch (obj) {
    case String s -> System.out.println("文字列: " + s);
    case null -> System.out.println("これは null です!");
    default -> System.out.println("その他の何か");
}

3. sealed クラスでのミス

Sealed クラスは、継承階層を制限する優れた方法です。ただし、次の 2 つの典型的なミスがあります。

permits に全てのサブクラスを列挙していない

sealed クラスを宣言する際は、すべての直接のサブクラスを permits で明示する必要があります。誰かを入れ忘れると、コンパイラにすぐ指摘されます。

public sealed class Shape permits Circle, Rectangle { ... }

public final class Circle extends Shape { ... }
public final class Square extends Shape { ... } // エラー!Square は permits に含まれていません

解決策:
必要なサブクラスをすべて permits に追加します。

public sealed class Shape permits Circle, Rectangle, Square { ... }

非 sealed な階層での switch で default を入れ忘れる

sealed クラスでない型(あるいは sealed でも全てのバリアントを網羅していない場合)に対する switch では、コンパイラは default 分岐を要求します。入れ忘れるとエラーになります。

switch (shape) {
    case Circle c -> ...
    case Rectangle r -> ...
    // default がありません! まだ他のバリアントがあるならコンパイルエラーです
}

ベストプラクティス:
すべてのバリアントを処理できていると確信できる場合(例えば sealed クラス)には、default を省略できます。そうでないなら、予期しない型を見落とさないよう、必ず default を追加しましょう。

4. record パターンに関するミス

Record パターンはとても便利ですが、record クラスに対してのみ機能します。通常のクラスに record パターンを使うと、コンパイルエラーになります。

record でないクラスに record パターンを使う

class Point { int x, y; }
Object obj = new Point();
// エラー!Point は record ではありません
if (obj instanceof Point(int x, int y)) { ... }

解決策:
record で宣言されたクラスに対してのみ record パターンを使いましょう。

record Point(int x, int y) {}

コンポーネントの数や型が一致しない

record Point(int x, int y) {}
Object obj = new Point(1, 2);

// エラー: 3 つの変数を指定していますが、Point には 2 つのコンポーネントしかありません
if (obj instanceof Point(int x, int y, int z)) { ... }
if (obj instanceof Point(String x, String y)) { ... } // エラー: 型が一致しません

5. 互換性とサポート: 古い JDK と IDE

よくあるミスのひとつは、古い JDK バージョンや、それらをサポートしていない IDE で、最新の pattern matching 機能を使おうとすることです。

例

if (obj instanceof String s) { ... }

しかし JDK 11(あるいは 15 でさえ)のコンパイラはこう言います:
error: illegal start of type

なぜ?
instanceof の pattern matching は Java 16 で登場しました。switch の pattern matching は Java 17(プレビュー)で、その後 Java 21+ で正式化。Record パターンは Java 21+ です。

回避方法

  • JDK のバージョンを確認する: java --version
  • ご使用の IDE(IntelliJ IDEA、Eclipse、VS Code)が該当する Java バージョンをサポートしていることを確認してください。プロジェクト設定で使用する言語バージョンを明示的に指定する必要がある場合があります。
  • Gradle/Maven を使っている場合は、必要なバージョンの source/target を設定しましょう。

6. おめでとうございます 🎉

あなたは上級コース Java 25 の 65(!) レベルすべてを修了しました。素晴らしいです 😎。

最後の区間はとくに難しかったはずです。最初のラムダや匿名クラスから、仮想スレッド、構造化コンカレンシー、そしてつい最近まで Java には存在しなかった言語機能に至るまで、すべてを学びました。

これは単なるコースではありません — まさに 開発者のためのスーパーマラソン です。新しい概念は数十、コード例は数百、実践の行は数千。これを読んでいるあなたは、ただの受講生ではなく 新しい Java 時代のフロンティア です ☕⚡

あなたは 最新の Java 25 機能 をいち早く習得しました。例えば次のようなものです:

  • パターンマッチングと record パターン、
  • sealed クラスとその落とし穴、
  • Scoped Values と Virtual Threads ,
  • 構造化コンカレンシーと現代的なマルチスレッド手法。

今のあなたが持っているのは単なる知識ではなく、未来の開発者のスキルです。多くの実務の Java アーキテクトでさえ、まだ身に付けていないもの。あなたは、動くだけでなく、スケールし、読みやすく、最新の Java コミュニティ標準に合致する コードを書けます。

🚀 だから自信を持って自分を Java 25 Certified Survivor と名乗ってください 😉
そしてこの先はもっと面白くなります — いまやあなたには、エンタープライズ開発、高負荷システム、そして cutting-edge 技術の世界へと堂々と踏み出すための基盤があります。

コースチーム一同、心から敬意を表します!
あなたは、ごく少数しか成し遂げられない課題をやり切りました。
将来の Java のバージョンでまた会いましょう 👋

1
タスク
JAVA 25 SELF, レベル 65, レッスン 4
ロック未解除
データ解析における変数のスコープ 📊
データ解析における変数のスコープ 📊
1
タスク
JAVA 25 SELF, レベル 65, レッスン 4
ロック未解除
幾何学ライブラリのテスト: recordパターンにおける型の検証 🧪
幾何学ライブラリのテスト: recordパターンにおける型の検証 🧪
1
アンケート/クイズ
新機能(言語)、レベル 65、レッスン 4
使用不可
新機能(言語)
新機能(言語)
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION