進歩についていけない焦りを抱えた50代が、

若手のコードを理解できるようになることを目標に、Java7以降を一から学び直す記録です。
ラベル 再学習記録 の投稿を表示しています。 すべての投稿を表示
ラベル 再学習記録 の投稿を表示しています。 すべての投稿を表示

2026年2月8日日曜日

【Java進化史 第3回】Java7 - switch文は何を守り、何を変えなかったのか?

Java7には、もう一つ地味な変更がある。

switch文で String が使えるようになった ことだ。


■ Java6までのswitch

switchで使えるのは、 int や enum などの限定的な型だけだった。


switch (statusCode) {
    case 0:
        ...
        break;
    case 1:
        ...
        break;
}

文字列で分岐したい場合、 if-else を使うことが多かった。


if ("OK".equals(status)) {
    ...
} else if ("ERROR".equals(status)) {
    ...
}

あるいは、enumを用意して対応する。

少し回り道が必要だった。


■ Java7での変更

Java7からは、 Stringがswitchで使えるようになった。


switch (status) {
    case "OK":
        ...
        break;
    case "ERROR":
        ...
        break;
}

可読性は確かに上がる。

素直に書けるようになった。

これは小さいが、現場では確実に効く変更だ。


■ だが、変わらなかったものがある

それが fall-through だ。

breakを書かなければ、 次のcaseへ処理が流れる。


switch (level) {
    case 3:
        log("HIGH");
    case 2:
        log("MEDIUM");
    case 1:
        log("LOW");
        break;
}

これはC言語由来の仕様。

Javaはここを変えなかった。


■ 他言語との違い

近年の言語では、 fall-throughは基本的に採用されていない。

  • Kotlin → 自動で終了(break不要)
  • Swift → 自動で終了
  • Rust → fall-throughなし

一方で、CやC++では明示的なbreakが必要だ。

breakを書き忘れてバグになる。

経験のある人も多いのではないだろうか。


■ なぜJavaは残したのか?

理由は明確だ。

後方互換性

既存コードを壊さない。

Javaはこの原則を徹底している。

そしてもう一つ。

Javaは「削除」ではなく 「追加」で進化する言語だからだ。

古い構文は残す。

その上で、新しい選択肢を足していく。


■ C言語世代の安心感

50代後半以上のエンジニアの多くは、 C言語からキャリアを始めたのではないだろうか。

私もその一人だ。

fall-throughを見ると、 どこか安心する。

「ああ、これはCと同じだ」と。

JavaがCに似ている部分を残しているのは、 偶然ではない気がする。

だが同時に、 言語設計は少しずつ安全性と明確さへ向かっている。

守るものと、変えるもの。

そのバランスの上に、 Javaの進化はある。


■ まとめ

Java7のswitch変更は、 革命ではない。

だが、

Javaは「何を変えないか」を選び続けている。

それがJavaらしさだ。

守りながら、少しずつ進む。

それがこの言語の進化の形なのだと思う。





【Java進化史 第2回】Java7 - diamond演算子は何を変えたのか?

最初に見たとき、正直こう思った。

「なんじゃこりゃ?」

「そもそも演算子なのか?」

「三項演算子に似てるな…?」

だが、使ってみると――

地味に、楽。


■ Java6までの書き方


List<String> list = new ArrayList<String>();

型を2回書く。

宣言側と、インスタンス生成側。

Genericsが導入されたJava5以降、 この「2回書き」は当たり前だった。

特に型が長くなると、地味に辛い。


■ Java7で何が変わったのか


List<String> list = new ArrayList<>();

右側の型が消えた。

<> だけ。

これが diamond演算子 と呼ばれる。

見た目がダイヤモンドに見えるからだ。


■ 何が嬉しいのか?

  • 記述が短くなる
  • 可読性が上がる
  • 型変更が楽になる

例えば、


List<Integer> list = new ArrayList<Integer>();


List<Long> list = new ArrayList<Long>();

に変えるとき、 2箇所修正が必要だった。

diamondなら1箇所で済む。

これは地味に効く。


■ 本当に「演算子」なのか?

実は、厳密には演算子ではない。

Genericsの型推論を コンパイラに任せるための構文だ。

つまり、

型推論の第一歩


■ 2記事書いて感じたこと

正直に言うと、 私はこれまでJava7を体系的に学んだことがなかった。

今回あらためて調べ、 第1回のtry-with-resources、 そして今回のdiamond演算子を追ってみて思った。

Java7は派手ではない。

だが、

開発者の「面倒くささ」を確実に減らしている。

例外処理の煩雑さを減らし、 Genericsの重複記述を減らし、 小さなストレスを一つずつ削っている。

革命ではない。

だが、 確実に優しい進化だ。

この2本を書いてみて、 Java7は「地味だけど開発者想いのバージョン」だったのではないか、 と感じ始めている。




【Java進化史 第1回】Java7 - try-with-resourcesは何を変えたのか?

Java7は地味だと言われる。

だが、現場を救った機能がある。

それが try-with-resources だ。


■ 昔のclose地獄

Java6まで、リソースを扱うコードはこうだった。


FileInputStream fis = null;
try {
    fis = new FileInputStream("test.txt");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

何度これを書いただろう。

  • close忘れ
  • 二重try
  • ネスト地獄

そして一番怖いのは、 close忘れによるDB接続リークだ。

Javaから接続しているDBコネクションが解放されず、 接続数がMAXに達する。

ある日突然、全体が止まる。

原因は、たった一行のclose忘れ。

実際に、トラブルの火種になり得る。


■ JDBCコネクションプールとの関係

「でも今はコネクションプールがあるから大丈夫では?」

確かに、最近の現場では HikariCPなどのコネクションプールを使うのが普通だ。

だが重要なのはここだ。

close()は“破棄”ではない。

プール利用時のclose()は、 接続を物理的に切断するのではなく、 プールへ「返却」しているだけだ。

つまり、close()を呼ばなければ、 プールに戻らない。

結果として、

  • 接続が枯渇する
  • 待ちが発生する
  • 最悪、システム停止

try-with-resourcesは、 プール利用環境でも極めて重要なのだ。


■ 実務では自分で書かない?

正直に言うと、 DB接続処理などは共通部品化されていることが多い。

だから普段は、自分でcloseを書くことは少ない。

だが――

「ちょっとした検証コード」
「一時的なバッチ」
「ローカルでのテスト」

こういうときに、自分で書く。

そして、うっかりcloseを書き忘れる。

私はある。


■ Java7で何が変わったのか


try (FileInputStream fis = new FileInputStream("test.txt")) {
    // 処理
} catch (IOException e) {
    e.printStackTrace();
}

tryの丸括弧の中に「resource」を書く。

すると、ブロック終了時に自動でclose()が呼ばれる。

finallyは不要。

ネストも不要。


■ 名前の意味

try-with-resources。

直訳すれば、

「リソース付きtry文」。

リソース(=closeが必要なもの)を tryと一緒に宣言する。

だから、try with resources。


■ AutoCloseableとは何か

対象となるのは、 AutoCloseable を実装しているクラスだ。

つまり「close()メソッドを持つ型」。

  • ファイル(FileInputStream / BufferedReader など)
  • データベース(Connection / Statement / ResultSet)
  • ソケット(Socket)
  • ZipFile
  • Scanner

JDK標準ライブラリの多くはAutoCloseableに対応している。

「closeが必要なものは大体いける」と思ってよい。

さらに、自作クラスでも実装できる。


class MyResource implements AutoCloseable {
    public void close() {
        System.out.println("closed");
    }
}

これは単なる糖衣構文ではない。

リソース管理の統一ルールを作った機能なのだ。


■ Java6方式と混在しても動くのか?

結論から言えば、動く。

だが、保守性は確実に落ちる。

  • 書き方が統一されない
  • レビュー時の負担が増える
  • ミスの温床になる

可能であれば段階的に置き換えるべきだ。

もちろん、 予算と時間が許せば。

だが新規コードでは、必ず使う。


■ まとめ

派手さはない。

ラムダのような衝撃もない。

だが、

try-with-resourcesは、 「書きやすくした機能」ではない。

事故を減らすための設計思想だ。

Javaは派手に変わることもある。
だが、本当に現場を救うのは、
こういう地味な進化かもしれない。





【Java実行環境】ブラウザだけでJavaは動くのか?paiza.ioを試してみた

前回、MacにJDK21をインストールした。

Homebrewで入れて、HelloWorldまで動かした。

「よし、これで本格的にやるぞ」

…と思ったが、ふと考えた。

今って、ブラウザだけでJava動かせないのか?


■ 若い頃は、こんなサービスなかった

私が若い頃。

Javaを動かすには、必ず環境構築が必要だった。

  • JDKをダウンロード
  • パスを通す
  • コンパイルする

環境が壊れたら、半日つぶれる。

それが普通だった。

でも今は違う。

ブラウザを開くだけで、Javaが書ける。

いい時代になった。


■ paiza.ioを使ってみる(無料)

今回は、以前少し触ったことのある paiza.io を使ってみる。

https://paiza.io/ja/projects/new

無料で使えるオンライン実行環境だ。

特別なインストールは不要。

ブラウザでアクセスするだけ。


■ 使い方(超かんたん)

上のURLにアクセスすると、画面左上に緑色のボタンがある。

そこで言語を Java に変更する。

すると、次のようなテンプレートが表示される。


import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        
        System.out.println("XXXXXXXX");
    }
}

この


System.out.println("XXXXXXXX");

を、次のように書き換える。


System.out.println(System.getProperty("java.version"));

そして、左中ほどにある緑色の「実行」ボタンを押す。

すると、下の実行結果エリアに、Javaのバージョンが表示される。

(今日時点では)


18.0.2

と表示された。

ローカルに何も入れていなくても、Javaが動く。

正直、ちょっと感動する。


■ 昔のJavaでも動くのか?

ちなみに、


System.getProperty("java.version")

は、かなり昔のJavaから使えるメソッドだ。

Java6でも問題なく動く。

こういう「昔からあるAPI」を使うと、世代を超えて検証できるのが面白い。


■ 実際に使ってみた感想

いいところ:

  • すぐ試せる
  • 環境構築が不要
  • 無料で使える
  • ちょっとした検証には最適

気になるところ:

  • 実行がやや遅い
  • ブラウザなので入力スピードが出ない
  • コード補完などの支援は弱い

本気で開発するには少し厳しい。

でも、

「ちょっと試したい」
「若手のコードの一部を検証したい」

そんな用途には、十分すぎる。


■ ローカル環境との違い

前回、MacにJDK21をインストールした。

ローカル環境では:

  • 高速に実行できる
  • 複数バージョンを切り替えられる
  • 本格的な開発ができる

一方、ブラウザ環境は:

  • とにかく手軽
  • 準備ゼロ
  • すぐ試せる

用途が違う。

どちらが正しい、ではない。


■ まとめ

Javaは、昔よりもずっと始めやすくなっている。

環境構築で挫折する時代ではない。

でもやはり、本格的にやるならローカル環境は必要だ。




【Java進化史 第27回】Java9でSetとMapにも of() が? 〜 なんじゃこりゃ、の続き 〜

前回、こんなコードで手が止まった。 List<String> names = List.of("Tanaka", "Sato", "Suzuki"); List.of() 。 変更できないリストを、一...